File: DaqTest.m

package info (click to toggle)
psychtoolbox-3 3.0.19.14.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 86,796 kB
  • sloc: ansic: 176,245; cpp: 20,103; objc: 5,393; sh: 2,753; python: 1,397; php: 384; makefile: 193; java: 113
file content (1289 lines) | stat: -rw-r--r-- 50,682 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
function DaqTest
% DaqTest
%
% DaqTest assesses the Daq Toolbox, which provides communication with a
% particular USB data acquisition device (daq): the USB-1208FS made by
% Measurement Computing (see URL below). This daq costs $150 and offers "50
% kHz" input and output 12-bit sampling of analog voltages (8 in, 2 out)
% and 16 digital i/o lines, with signals brought out to screw terminals.
% ("50 kHz" is a theoretical upper limit: as of 18 April 2005 we attain 2
% kHz.) The USB-1208FS is the size of a wallet and is powered through its
% USB cable. The Daq Toolbox gives you complete control of it from within
% Matlab, via the PsychHID extension.
%
% DaqTest assesses all the functions provided by the USB-1208FS firmware.
% (Some risky tests, below, have been turned off, but can be re-enabled by
% the adventurous user.) DaqFunctions gives a brief description of every
% function.
%
% NOT RESPONDING? If PsychHID is not responding, e.g. after unplugging and 
% re-plugging the USB connector of your device, try quitting and restarting
% MATLAB. We find that this reliably restores normal communication. 
%
% web http://www.http://www.measurementcomputing.com/cbicatalog/directory.asp?dept_id=403 -browser;
% web http://psychtoolbox.org/daq.html -browser;
% See also: Daq, DaqFunctions, DaqPins,PsychHIDTest,PsychHID,PsychHardware,
% DaqDeviceIndex, DaqDIn, DaqDOut, DaqAIn, DaqAOut, DaqAInScan, DaqAOutScan

% 3/21/05 dgp Denis Pelli wrote it.
% 3/28/05 dgp Corrected reportID and reportBytes.
% 3/30/05 dgp More error checking.
% 3/31/05 dgp Added the rest of the functions.
% 4/2/05  dgp The input functions now work, for the first time.
% 4/15/05 dgp Polished.
% 4/15/05 dgp Merged arguments in calls to DaqAOutScan and DaqAInScan.
% 4/25/05 dgp Nearly eliminated crash associated with CLEAR MEX.
% 4/26/05 dgp Fixed DaqAInScan to return sensible results.
% 8/26/05 dgp Incorporated bug fix for compatibility with Mac OS X Tiger 
%             suggested by Maria Mckinley <parody@u.washington.edu>. The reported
%             number of outputs of the USB-1208FS has changed in Tiger.
%             http://groups.yahoo.com/group/psychtoolbox/message/3614
% 11/xx/07 - 
%  1/xx/08 mpr  Instituted various fixes to get this to work for a USB-1608FS
%                   in Leopard
% 05/11/09 mk Add if isempty(FinalStatus) in line 444 and later to catch
%             empty returns from DaqGetStatus.

debugging=0; % Used by dgp to track down a crash in PsychHID.

% Do we have a USB-1208FS daq? Each such box will present itself as four
% HID "devices" sharing the same serial number.  For 1608FS, there may be 5, 6,
% or 7 devices.  Don't know why the variation...  Should be 7...  Most commands
% will work even if only five interfaces are found, but the most important
% commands -- the ones that read digitized analog signals -- require all seven
% interfaces unless you're willing to lose some data.  So we'll try to make sure
% all are found before continuing.
daq=DaqDeviceIndex([],0);

if isempty(daq)
  % check again because user might have run PsychHID('Devices') and then plugged
  % in the daq.  This should fix that.
  clear PsychHID;
  daq = DaqDeviceIndex([],0);
end

devices=PsychHID('Devices');
fprintf('\n');
switch length(daq)
  case 0,
    fprintf('Sorry. Couldn''t find any USB-1208FS, -1408FS, or -1608FS boxes connected to your computer.\n');
    return;
  case 1,
    fprintf('Yay. I found a %s daq!  Serial number is: %s\n',devices(daq).product,devices(daq).serialNumber);
    if strcmp(devices(daq).product(5:6),'16')
      eval(['[' sprintf('AllSNs{%d},',1:(length(devices)-1)) 'AllSNs{' int2str(length(devices)) '}] = deal(devices.serialNumber);']);
      NumInterfaces = length(cell2mat(strfind(AllSNs,devices(daq).serialNumber)));
      if NumInterfaces ~= 7
        ConfirmInfo(sprintf('Found %d interfaces where there should be 7.  Run "help DaqReset" for suggestions; then re-run "DaqTest"',NumInterfaces));
        return;
      end
    end
    numTries = 0;
    TheLEDBlinked = 0;
    while ~TheLEDBlinked
      ConfirmInfo('Direct your attention to the LED on the device and then click the "okay" button here:');
      err=DaqBlinkLED(daq);
      if err.n
        fprintf(['\nUh oh... there was a problem when I told your device to blink its LED.\n' ...
                 'I haven''t seen this before, so I don''t know what''s going on.  This is\n' ...
                 'what PsychHID told me about the problem, though:\n\n']);
        err
        fprintf('\nI''ll let you try to fix the problem and then come back to me.  Bailing now!\n\n');
        return;
      end
      TheLEDBlinked = TwoStateQuery('Did the LED just blink for you?');
      if TheLEDBlinked < 0
        ConfirmInfo('Please click yes or no... do not close the window any other way!');
        TheLEDBlinked = TwoStateQuery('Did the LED blink for you earlier?');
        if TheLEDBlinked < 0
          ConfirmInfo('You do not seem to play well with others.  I am quitting on you!');
          return;
        end
      end
      numTries = numTries+1;
      if numTries > 1 && ~TheLEDBlinked
        ConfirmInfo('It should have blinked.  Since it didn''t and there were no obvious errors I will bail and let you work on it.');
        return;
      end
    end
  case 2,
    fprintf('Yay. You have two daqs!');
    numTries = 0;
    TheLEDBlinked = 0;
    while ~TheLEDBlinked
      if strcmp(devices(daq(1)).product(5:6),'16')
        eval(['[' sprintf('AllSNs{%d},',1:(length(devices)-1)) 'AllSNs{' int2str(length(devices)) '}] = deal(devices.serialNumber);']);
        NumInterfaces = length(cell2mat(strfind(AllSNs,devices(daq(1)).serialNumber)));
        if NumInterfaces ~= 7
          ConfirmInfo(sprintf('Found %d interfaces where there should be 7.  Run "help DaqReset" for suggestions; then re-run "DaqTest"',NumInterfaces));
          return;
        end
      end
      fprintf('\nI''m about to try device with serial number: %s\n',devices(daq(1)).serialNumber);
      ConfirmInfo('Look at the LED on the daq you want to test and then click this button:');
      err=DaqBlinkLED(daq(1));
      if err.n
        fprintf(['\nUh oh... there was a problem when I told your first device to blink its LED.\n' ...
                 'This is the error message I received:\n\n']);
        err

        fprintf('\nI will move on to the second one anyways and hope for the best.\n');
      end

      TheLEDBlinked = TwoStateQuery('Did the LED blink on the device you want to test?');
      if TheLEDBlinked < 0
        fprintf('\nYou should have clicked "Yes" or "No".  I am taking your response as a "No".\n');
        TheLEDBlinked = 0;
      end
      if TheLEDBlinked
        daq = daq(1);
        break;
      else
        if strcmp(devices(daq(2)).product(5:6),'16')
          eval(['[' sprintf('AllSNs{%d},',1:(length(devices)-1)) 'AllSNs{' int2str(length(devices)) '}] = deal(devices.serialNumber);']);
          NumInterfaces = length(cell2mat(strfind(AllSNs,devices(daq(2)).serialNumber)));
          if NumInterfaces ~= 7
            ConfirmInfo(sprintf('Found %d interfaces where there should be 7.  Run "help DaqReset" for suggestions; then re-run "DaqTest"',NumInterfaces));
            return;
          end
        end
        fprintf('I''m about to try device with serial number: %s\n',devices(daq(2)).serialNumber);
        Confirm('Look again at the LED on the device you want to test and then click this button:');
        err=DaqBlinkLED(daq(2));
        if err.n
          fprintf(['\nUh oh... there was a problem when I told your second device to blink its LED.\n' ...
                   'This is the error message I received:\n\n']);

          err              
        end
        TheLEDBlinked = TwoStateQuery('Did the LED blink on the device you want to test?');
        if TheLEDBlinked < 0
          fprintf('\nYou should have clicked "Yes" or "No".  I am taking your response as a "No".\n');
          TheLEDBlinked = 0;
        end
        if TheLEDBlinked
          daq = daq(2);
          break;
        end
      end
      numTries = numTries+1;
      if numTries > 1 && ~TheLEDBlinked
        ConfirmInfo('I don''t know why this didn''t work.  I hope you do because I am bailing!');
        return;
      end
    end % while ~TheLEDBlinked
  otherwise,
    fprintf('Yay. You have %d daqs (the first one is a %s): \n',length(daq),devices(daq(1)).product);
    numTries = 0;
    TheLEDBlinked = 0;
    while ~TheLEDBlinked
      for k=1:length(daqs)
        if strcmp(devices(daq(k)).product(5:6),'16')
          eval(['[' sprintf('AllSNs{%d},',1:(length(devices)-1)) 'AllSNs{' int2str(length(devices)) '}] = deal(devices.serialNumber);']);
          NumInterfaces = length(cell2mat(strfind(AllSNs,devices(daq(k)).serialNumber)));
          if NumInterfaces ~= 7
            ConfirmInfo(sprintf('Found %d interfaces where there should be 7.  Run "help DaqReset" for suggestions; then re-run "DaqTest"',NumInterfaces));
            return;
          end
        end
        fprintf('About to test device %d, serial number: %s\n',k,devices(daq(k)).serialNumber);
        ConfirmInfo('Look at the LED on the device you want to test and click "Okay" when ready');
        err=DaqBlinkLED(daq(k));
        if err.n
          fprintf('Uh-oh... there was an error when I tried to blink the LED on device %d.  It was:\n\n',k);
          err
          fprintf('I will proceed anyways...');
        end
        TheLEDBlinked = TwoStateQuery('Did the LED blink on the device you wanted to test?');
        if TheLEDBlinked < 0
          fprintf('You should have clicked "yes" or "no".  I am taking your response as "no"');
          TheLEDBlinked = 0;
        end
        if TheLEDBlinked
          daq = daq(k);
          break;
        end
        if numTries > 1
          ConfirmInfo('I tried each LED twice...  I am giving up now.  Sorry!');
          return;
        end
        numTries = numTries+1;
      end % for k=1:length(daqs)
    end % while ~TheLEDBlinked
end % switch length(daq)

if strcmp(devices(daq).product(5:6),'16')
  Is1608=1;
else
  Is1608=0;
end

% After passing through the above code, daq should be a scalar.  References to
% it as "daq(1)" are a legacy of prior versions.  Not deemed worth fixing.  --
% mpr

if debugging
  % line numbering is... well, I think this used to be line 67...
% 	fprintf('TestClearMex once crashed at line 67.\n');
    TestClearMex(daq);
end

% fprintf(['\n** NOT RESPONDING? If your %s is not responding, try quitting and\n'...
%     '** restarting MATLAB. Denis found that this reliably restored normal\n'...
%     '** communication for his device.\n'],devices(daq(1)).product);
if strcmp(devices(daq(1)).product,'USB-1208FS') || strcmp(devices(daq(1)).product,'PMD-1208FS') || strcmp(devices(daq(1)).product,'USB-1408FS')  
  fprintf(['\n'...
      '** WIRING THE PINS OF THE USB-1208FS (and presumably -1408FS)\n'...
      '**    For the analog i/o test, please connect both channels of analog\n'...
      '** output to the first two channels of differential analog input:\n'...
      '** Connect pin 1 to 13, 2 to 12, 4 to 14, and 5 to 12.\n'...
      '**    If you''ve got one, you may want to attach a speaker or oscilloscope\n'...
      '** to analog output channel 0 (pin 13) and analog ground (pin 12). \n'...
      '**    Or you may want to connect to bit 0 of digital output port A (pin 21) \n'...
      '** and digital ground (pin 29).\n']);
elseif strcmp(devices(daq(1)).product,'USB-1608FS')
   fprintf(['\n** If you want to run all the tests we have here, you should connect analog\n' ...
            '** port 0 (pin 1) to the first bit of the digital port (pin 21).  If you would\n' ...
            '** like to test your counter, you should also connect pin 21 to the counter\n' ...
            '** terminal (pin 38).  Measurement Computing recommends that you ground any\n' ...
            '** analog ports that you are not using.  To follow that advice, connect pin 3\n' ...
            '** to pin 4, pin 5 to pin 6, pin 7 to pin 8, pin 9 to pin 10, pin 11 to pin 12,\n' ...
            '** pin 13 to pin 14, and pin 15 to pin 16.\n\n']);
else
  fprintf('Your device has not been tested with this toolbox.  You should verify the wiring and edit DaqTest to comply with it.\n');
  return;
end

ConfirmInfo(['A lot of information will be written to the Matlab command window.  ' ...
             'You can ignore most of it, but you should look at the command window now.']);

drawnow;

% The USB-1208FS is a composite device. It has four interfaces (0,1,2,3)
% which are each represented as a device in the list returned by
% PsychHID('Devices'). In calling the Daq functions, the user supplies us
% only the device index "device" corresponding to interface 0 of the
% desired USB-1208FS. However, the reports containing the samples arrive on
% interfaces 1,2,3. As returned by PsychHID('Devices'), interface i is at
% device-i, and we proceed on that basis after doing a quick check to
% confirm our assumption. However, to be platform-independent, it would be
% better to actually find all four device interfaces and confirm their
% interface numbers. USB Probe reports interface numbers, but, as far as I
% can tell, Apple's HID Explorer and our PsychHID do not return this 
% information. However, PsychHID('Devices') does report the number of outputs: 
% the USB-1208FS interface 0 has 229 (pre-Tiger) 70 (Tiger) outputs, interface 1
% has 65 (pre-Tiger) 1 (Tiger) outputs, and interfaces 2 and 3 have zero 
% outputs.  I have no idea why the number of outputs changed with the arrival of
% Mac OS X Tiger.
% 
% The USB-1608FS under Leopard behaves quite differently.  It has seven
% interfaces, no six... no five interfaces... so far I've had the system come
% up each of those ways and in that order...  In all cases, though, all but the 
% last (read highest index in the array returned by "PsychHID('Devices')") of 
% the interfaces have had 1 input, no outputs, and one collection.  The last
% interface (I am currently presuming interface 0) has 18 inputs, 66 outputs, 
% and 1 collection for a total of 85 totalElements.  I tried Tiger once and 
% found six interfaces.  Then I rebooted in Leopard again and found six 
% interfaces again as well.  Only difference seemed to be that Leopard 
% recognized the Apple Studio Display in my call to PsychHID, and Tiger didn't.
devices=PsychHID('Devices');
for d=daq 
  ok= (d-3>=1 && (devices(d-1).outputs==65 || devices(d-1).outputs==1)) || (d+3<=length(devices) && (devices(d+1).outputs==65 || devices(d+1).outputs==1));
  if devices(d).outputs<70 && ok
    fprintf(['If you have a 1408FS, you should just have been given a message\n' ...
             'suggesting some changes in the software.  If you are seeing this \n' ...
             'message, you are probably the first person to test a 1408 with the\n' ...
             'daq toolbox.\n']);
    error(sprintf('Invalid device, not the original USB-1208FS or USB-1608FS.'));
  end
end

if debugging
    TestClearMex(daq);
end

% Disable EEPROM read/write tests by default. Having this on by default is
% just bat-shit crazy!!!
if 0
  % Denis originally did not test the memory read and write functions because he
  % was afraid of messing up his firmware.  However, since this was one of the
  % first sets of functions from which I got interpretable test results, I added
  % some safeguards to DaqMemWrite and added tests of the functions here. -- mpr
  fprintf('\nTesting my ability to read and write your daq device''s EEPROM...');

  [TheOriginalData,TheErrors] = DaqMemRead(daq(1),512,59);
  MemoryReadError = 0;
  for k=1:length(TheErrors)
    if TheErrors(k).n
      MemoryReadError = 1;
      TheErrors(k)
    end
  end

  if MemoryReadError
    fprintf(['\nYou should have just been told of at least one error that occurred when I\n' ...
             'tried to read the EEPROM of your daq device.  Since it failed this test, I\n' ...
             'am aborting.  Sorry things didn''t work out...\n\n']);
    return;
  end

  MemWriteTestData = 1:59;

  fprintf('\nMemory was apparently read successfully...');
  err=DaqMemWrite(daq(1),512,MemWriteTestData);
  if err.n
    fprintf(['\nUh oh... an error occurred when I tried to write to the EEPROM of your daq\n' ...
             'device.  Since that test failed, I am aborting.  I hope that I have not screwed\n' ...
             'up the memory of your device...  In any case, I am bailing out now.  Good\n' ...
             'luck fixing things!  What I was told was:\n\n']);
    err
    return;
  end

  fprintf('\nMemory was apparently written successfully...');

  [TheWrittenData,TheErrors] = DaqMemRead(daq(1),512,59);
  MemoryReadError = 0;
  for k=1:length(TheErrors)
    if TheErrors(k).n
      MemoryReadError = 1;
      TheErrors(k)
    end
  end

  if MemoryReadError
    fprintf(['\nUh oh... I spoke too soon.  As you should just have been told, there was at\n' ...
             'least one error when I tried to read from your daq device a second time.  Odd that\n' ...
             'the device passed such a test once and then failed...  but that''s how things look\n' ...
             'to me.\n']);
    return;
  end

  if ~all(TheWrittenData(2:end) == MemWriteTestData)  
    fprintf(['\nUh oh...  I spoke too soon.  The data that I just read from the EEPROM of your\n' ...
             'daq device does not match the data that I think I just wrote to it.  I do not know\n' ...
             'why that might be.  Did you unplug it (sorry for such a lame question...).\n\n']);
    return;
  end

  fprintf('\nI just read what I wrote, and it looks like I wrote what I thought I wrote!');

  err=DaqMemWrite(daq(1),512,TheOriginalData(2:end));
  if err.n
    fprintf(['\nHmmmm...  I just tried to write your original data back to the EEPROM of your daq\n' ...
             'device.  That operation apparently failed.  I hope that I did not do any serious\n' ...
             'damage here...  It is unlikely that I did, but it is also unlikely that this function\n' ...
             'would fail here when it worked before.  Sorry things didn''t go more smoothly.  This\n' ...
             'is all I can tell you about the problem:\n\n']);
    err
    fprintf(['If you want to take matters into your own hands, the data I originally read from your\n' ...
             'daq''s EEPROM was:\n\n']);
    TheOriginalData(2:end)
    return;
  end

  fprintf(['\nEEPROM of your daq device has been restored to what it was before this test began.\n' ...
           'So far so good!\n\nMoving on to test mode changes...']);
else
  fprintf('\n\nMoving on to test mode changes...');
end

TheStatus = DaqGetStatus(daq);
if isempty(TheStatus)
  fprintf(['\nFailed to receive status report...  Look inside DaqGetStatus and run\n' ...
           'individual commands to try to figure out why this did not work.  In the\n' ...
           'mean time, I will take my leave of you.\n\n']);
  return;
else
  if isfield(TheStatus,'master')
    DaqSetSync(daq,TheStatus.master);
    NewStatus = DaqGetStatus(daq);
    if xor(TheStatus.master,NewStatus.master)
      DaqSetSync(daq,~TheStatus.master);
    else
      fprintf(['\nIt looks like I had trouble flipping the master sync status bit\n' ...
               'I don''t want to mess things up, so I return control to you.\n\n']);
      return;
    end
    FinalStatus = DaqGetStatus;
    if FinalStatus.master ~= TheStatus.master
      fprintf(['\nIt looks like I had trouble re-setting the master sync status bit\n' ...
               'after I changed it.  I am going to stop now.  I hope I haven''t caused a problem.\n\n']);
      return;
    else
      fprintf('\nSuccessfully toggled sync status bit.  Moving on...');
    end
  else
    fprintf('\nThere was a status returned, but it was missing the "master" field.  I will bail.\n\n');
    return;
  end % if isfield(TheStatus,'master'); else
  if isfield(TheStatus,'rising')
    DaqSetTrigger(daq,~TheStatus.rising);
    NewStatus = DaqGetStatus(daq);
    if xor(TheStatus.rising,NewStatus.rising)
      DaqSetTrigger(daq,TheStatus.rising);
    else
      fprintf(['\nIt looks like I had trouble flipping the trigger rising status bit\n' ...
               'I don''t want to mess things up, so I return control to you.\n\n']);
      return;
    end
    FinalStatus = DaqGetStatus;
    if FinalStatus.rising ~= TheStatus.rising
      fprintf(['\nIt looks like I had trouble re-setting the trigger rising status bit\n' ...
               'after I changed it.  I am going to stop now.  I hope I haven''t caused a problem.\n\n']);
      return;
    else
      fprintf('\nSuccessfully toggled trigger status bit.  Moving on...');
    end
  else
    fprintf('\nThere was a status returned, but it was missing the "rising" field.  I will bail.\n\n');
    return;
  end % if isfield(TheStatus,'rising'); else
  if isfield(TheStatus,'program')
    DaqPrepareDownload(daq,~TheStatus.program);
    NewStatus = DaqGetStatus(daq);
    if xor(TheStatus.program,NewStatus.program)
      DaqPrepareDownload(daq,TheStatus.program);
    else
      fprintf(['\nIt looks like I had trouble flipping the update program mode bit\n' ...
               'I don''t want to mess things up, so I return control to you.\n\n']);
      return;
    end
    FinalStatus = DaqGetStatus;
    if isempty(FinalStatus)
      fprintf(['\nIt looks like I had trouble reading the updated status from the device\n' ...
               'I don''t want to mess things up, so I return control to you.\n\n']);
      return;
    end
    if FinalStatus.program ~= TheStatus.program
      fprintf(['\nIt looks like I had trouble re-setting the update program mode bit\n' ...
               'after I changed it.  I am going to stop now.  I hope I haven''t caused a problem.\n\n']);
      return;
    else
      fprintf('\nSuccessfully toggled program status bit.  Moving on...\n');
    end
  else
    fprintf('\nThere was a status returned, but it was missing the "program" field.  I will bail.\n\n');
    return;
  end % if isfield(TheStatus,'program'); else
  
end

fprintf('\n');

fprintf('\nThe following tests assess all the %s commands, reporting any errors.\n',devices(daq(1)).product);
fprintf('\n** DIGITAL COMMANDS \n** DaqDConfigPort, DaqDIn, ');

if Is1608
  fprintf('and DaqDOut.\n\nDaqDConfigPort: configuring digital port for output.\n');
  err=DaqDConfigPort(daq,0);
  if err.n
    fprintf('Attempt to configure digital port failed.  This is all I can tell you about that:\n\n');
    err
  end
else
  % DaqDConfigPort
  fprintf('DaqDOut, and DaqGetAll.\n\nDaqDConfigPort: configuring digital ports for output.\n');
  err=DaqDConfigPort(daq(1),0,0); % configuring digital port A for output
  err=DaqDConfigPort(daq(1),1,0); % configuring digital port B for output
end

% I never had the following problem, so I don't know how helpful this is... --
% mpr

% Make sure the USB-1208FS is "attached".
if streq(err.name,'kIOReturnNotAttached')
    fprintf(['\nkIOReturnNotAttached: Mac OS error message says %s is "not attached".\n'...
        'But we know it is. We suggest that you quit and restart MATLAB. In our experience\n'...
        'that always clears up the problem.\n'],devices(daq(1)).product);
    error(sprintf('%s not attached.',devices(daq(1)).product));
end

% DaqDOut
if Is1608
  fprintf(['\nDaqDOut: random test patterns on DIO port. This is a basic functionality\n'...
      'test, showing that we can indeed read back what we wrote.\n']);
  a=Randi(255);
  err=DaqDOut(daq,a);
  fprintf('DaqDOut: %3d.\n',a);  
else % if Is1608 (DaqDOut test)
  fprintf(['\nDaqDOut: random test patterns on ports A and B. This is a basic functionality\n'...
      'test, showing that we can indeed read back what we wrote.\n']);
  a=Randi(255);
  err=DaqDOut(daq(1),0,a);
  b=Randi(255);
  err=DaqDOut(daq(1),1,b);
  fprintf('DaqDOut: %3d %3d.\n',a,b);
end % if Is1608; else (DaqDOut test)

if debugging
    TestClearMex(daq);
end

% DaqDIn
if Is1608
  fprintf('\nDaqDIn: reading digital port.\n');
  data=DaqDIn(daq);
  if isempty(data)
    disp('No data received.  That seems pathological so I will stop and let you investigate the problem.');
    return;
  else
    fprintf('DaqDIn: %3d.\n',data);
    if data ~= a
      fprintf(['What I read and what I wrote are not the same.  I will stop and let you see if\nyou can figure out why.\n' ...
               'My first guess is that you have grounded one or more of the DIO pins.  Even with the port configured\n' ...
               'for output, that seems to screw things up.  Disconnect all wires from the DIO terminals and try running\n' ...
               'DaqTest again.\n\n']);
      return;
    else
      disp('Data read matches data written.  Excellent!');
    end
  end
else % if Is1608 (DaqDIn test)
  fprintf('\nDaqDIn: reading digital ports.\n');
  data=DaqDIn(daq(1));
  if ~isempty(data)
    fprintf('DaqDIn: %3d %3d.\n',data);
    if length(data) ~= 2 || ~all(data == [a b])
      disp('Mismatch between what I read and what I wrote.  I will stop to let you investigate.');
      return;
    else
      disp('Data read matches what was written.  Excellent!');
    end
  else
    disp('No data received.  That seems pathological so I will stop and let you investigate the problem.');
    return;
  end
end % if Is1608; else (DaqDIn test)

% Bit functions
if Is1608
  fprintf('\nAbout to test ability to configure, read, and write individual bits...');
  
  fprintf('\nTwo''s complement of randomly chosen value: %d\n',bitcmp(a,8));
  TheBitValues = zeros(1,8);
  for k=1:8
    TheBitValues(k) = bitget(bitcmp(a,8),k);
  end
  DaqDWriteBit(daq,0:7,TheBitValues);
  TheResults = DaqDReadBit(daq,0:7);
  if ~all(TheResults == TheBitValues)
    disp('When I tried to write and read individual bits I came up with a different answer.  Stopping for you to investigate.');
    return;
  end
  TheWrittenValue = DaqDIn(daq);
  if TheWrittenValue == bitcmp(a,8)
    fprintf(['\nYes, the value I read back is the same as the bit complement of the previously written value!\n\n' ...
             'This test was not terribly stringent, and none of the DIO tests really check to see that your\n' ...
             'device accurately reads the inputs.  If you want to test that, you can do this:\n\n' ...
             '     DaqDConfigPort(device,1);\n\n' ...
             'and then try various combinations of wiring.  To check the value being read by all terminals at once,\n' ...
             'use:\n\n' ...
             '     DaqDReadBit(device,0:7)\n\n' ...
             '(no semi-colon at the end because you want to see the output).  Any of the channels connected to\n' ...
             'ground should read 0; others should read 1.  So, for instance, if you wire pin 21 to pin 22, pin 25\n' ...
             'to pin 26, and pin 33 to pin 34, and ran the DaqReadBit command, you should get:\n\n' ...
             '          0     1     0     1     1     1     0     1\n\n' ...
             'as an answer.  Equivalently, DaqDIn should return 186 in that case.  It is also possible to configure\n' ...
             'individual bits independently.  When I tried it I got behavior I did not fully expect (for instance,\n' ...
             'configuring a bit as output doesn''t always set the value of that bit when you write to it... as if\n' ...
             'the state of the bit when read is taken from an actual reading even though it shouldn''t be.  I did not\n' ...
             'test this too carefully, but I have no current reason to believe that there are any software errors in\n' ...
             'DaqDConfigPortBit.\n\n']);
  else
    fprintf(['Uh-oh, when I tried to read the whole port again as a single 8-bit value, I got\n' ...
             'a different answer.  Stopping for you to figure out why.\n\n']);
    return;
  end
else % if is1608 (Bit functions test)
  disp('Bitwise DIO functions have not been written for -1208 and/or -1408 daqs.  If these functions');
  disp('are important to you, you should edit them (DaqDConfigPortBit, DaqDWriteBit, DaqDReadBit) and');
  disp('then edit DaqTest so that the functions are tested on your hardware.');
  fprintf('\n\n');
end % if is1608; else (Bit functions test)

if debugging
    TestClearMex(daq);
end

% DaqGetAll
if Is1608
  fprintf('\nA working version of DaqGetAll has not been produced for the 1608, so skipping this test.\n');
else
  fprintf('\nDaqGetAll: reading all analog and digital inputs.\n');
  data=DaqGetAll(daq(1));
  if isempty(data)
    fprintf('Nothing received.\n');
  % I put this here before I set program to skip this test for 1608; if you fix
  % DaqGetAll, you will still need something like this as the 1608 has only the
  % one digital port compared to the 1208's two ports.  -- mpr
  elseif Is1608
    fprintf('data.digital: %3d.\n',data.digital);
  else
    fprintf('data.digital: %3d %3d.\n',data.digital);
  end
end
if debugging
    TestClearMex(daq);
end

% DIn/DOut speed test

fprintf(['\nDaqDOut & DaqDIn: write & read back one hundred random values as fast as\n' ...
         'possible. This test assesses reliability and latency, the time for data to \n' ...
         'go from host to device and back.\n']);
       
wrong=0;
missing=0;
if Is1608
  t=GetSecs;
  for trials=1:100
    % DaqDOut
    a=Randi(255);
    err=DaqDOut(daq,a);
    
    % Tried the following command instead of the previous command to see if 
    % the device is excessively slowed by the additional wrapping material in 
    % DaqDOut necessitated by not knowing in advance what type of Daq the user
    % has.  Found that it made *NO* difference! -- mpr
    %
    % PsychHID('SetReport',daq,2,4,uint8([0 a]));
    
    % DaqDIn
    data=DaqDIn(daq,1);
    if ~isempty(data)
      if a~=data
        wrong=wrong+1;
      end
    else
      missing=missing+1;
    end
    if err.n
      break;
    end
  end
  t=GetSecs-t;
else
  t=GetSecs;
  for trials=1:100
    % DaqDOut
    a=Randi(255);
    err=DaqDOut(daq(1),0,a);
    % DaqDIn
    data=DaqDIn(daq(1),2);
    if ~isempty(data)
      if a~=data(1)
        wrong=wrong+1;
      end
    else
      missing=missing+1;
    end
    if err.n
      break;
    end
  end
  t=GetSecs-t;
end

if missing==trials
    fprintf('Nothing received.\n');
else
    fprintf('Achieved %.0f Hz, i.e. %.0f ms cycle time. %.0f errors and %.0f missing in %.0f trials.\n',...
        trials/t,1000*t/trials,wrong,missing,trials);
end
if debugging
    TestClearMex(daq);
end

% DaqDOut
if Is1608
  fprintf('\nDaqDOut: producing fast squarewave digital output.\n');
  DaqDConfigPort(daq,0); % output
  for i=1:500
    err=DaqDOut(daq,255);
    err=DaqDOut(daq,0);
    if err.n
      break;
    end
  end
else
  fprintf('\nDaqDOut: producing fast squarewave digital output on port A.\n');
  DaqDConfigPort(daq(1),0,0); % output
  for i=1:500
    err=DaqDOut(daq(1),0,255);
    err=DaqDOut(daq(1),0,0);
    if err.n
      break;
    end
  end
end % if Is1608; else (DaqDOut test II)

if debugging
    TestClearMex(daq);
end

if Is1608
  CalibrateNow=TwoStateQuery('If you would like to calibrate analog channel 0 (recommended), wire pin 1 to pin 17 now. ',{'Okay','Skip'});
  if CalibrateNow > 0
    DaqCalibrateAIn(daq,0);
  end
  DoSquareTest = TwoStateQuery('Is pin 1 wired to pin 21?');
  if DoSquareTest > 0
    
    fprintf(['\n\nPutting square wave output through Digital Port bit 0 and reading it through\n' ...
             'Analog Input Channel 0...\n']);
           
    options.lowChannel = 0;
    options.highChannel = 0;
    options.range = 1;
    options.count = Inf;
    options.f = 100;
    
    DaqDConfigPort(daq,0);
    DaqDOut(daq,0);
    TheState=0;
    
    TheParams=DaqAInScanBegin(daq,options);

    TheInitialStart = GetSecs;
    WaitSecs(0.125);

    TheStart = GetSecs;

    for k=1:11
      AlreadyFlipped=0;
      while GetSecs-TheStart < k/4
        if ~AlreadyFlipped
          TheState = rem(TheState+1,2);
          DaqDOut(daq,TheState);
          AlreadyFlipped = 1;
        end
      end
    end
    
    WaitSecs(0.1);
    [TheData,TheParams] = DaqAInScanEnd(daq,options);

    TotalTimeElapsed = GetSecs-TheInitialStart;

    fprintf('Time elapsed: %f seconds\n',TotalTimeElapsed);
    fprintf('Number of data points: %d\n',length(TheData));
    fprintf('Expected number of data points: %d\n\n',floor(TheParams.fActual*TotalTimeElapsed));

    figure('Tag','DaqTestFig'); 
    plot((0:(size(TheData,1)-1))/TheParams.fActual-TheStart+TheInitialStart,TheData,'LineWidth',3);
    xlabel('Time (Seconds)');
    ylabel('Potential (Volts) ');
    title(sprintf('This should be a 5 V square wave with\na frequency of 2 Hz sampled at 100 Hz'));
    grid on;
    drawnow;
  end    
else % Is1608 (DaqAOut tests)
  fprintf('\n** ANALOG COMMANDS \n** DaqAIn, DaqAOut, DaqAInScan, DaqAOutScan, DaqALoadQueue\n');

  % DaqAOut: 1 kHz squarewave
  outTick=0.0005; % s
  duration=0.5; % s
  fprintf('\nDaqAOut: producing %.0f kHz squarewave output voltage for %.1f s.\n',0.5/outTick/1000,duration);
  tuntil=GetSecs;
  for i=1:duration/outTick
    tuntil=tuntil+outTick;
    WaitSecs(tuntil-GetSecs);
    err=DaqAOut(daq(1),0,mod(i,2)); % D/A 0
    err=DaqAOut(daq(1),1,mod(i,2)); % D/A 1
    if err.n
      break;
    end
  end

  % DaqAOut & DaqAIn: 4 Hz sinewave
  f=4;
  fprintf([
      '\nDaqAOut & DaqAIn: producing %.0f Hz sinewave and triangle wave output voltages,\n'...
      'on two channels, and reading them back in through the analog inputs. We plot \n'...
      'the readings in Figure 1. (It''s just noise unless you''ve installed wires\n'...
      'connecting output to input.)\n'],f);
  start=GetSecs;
  time=0:0.01:0.5;
  x=f*2*pi*time;
  sineWave=0.5+0.5*sin(x);       % Raised sine. Positive.
  triangleWave=0.5+0.5*trin(x);  % Raised triangle. Positive.
  v0=[];
  v1=[];
  for i=1:length(time)
    WaitSecs(time(i)+start-GetSecs);
    err=DaqAOut(daq(1),0,sineWave(i));
    err=DaqAOut(daq(1),1,triangleWave(i));
    if err.n
      break;
    end
    v0(i)=DaqAIn(daq(1),0,3);
    v1(i)=DaqAIn(daq(1),1,3);
  end
  if ~isempty(v0)
    figure(1);
    plot(time,v0,'r',time,v1,'g');
    ylabel('Volts');
    xlabel('Time (s)');
    title('Two channels (sine and triangle waves) put out by DaqAOut and read back in by DaqAIn.');
    text(0.15,1.9,'This graph will be meaningless noise unless you previously');
    text(0.15,1.8,'connected output to input. This test requires 4 wires ');
    text(0.15,1.7,'connecting analog output to input. Connect pin 1 to 13, ');
    text(0.15,1.6,'2 to 12, 4 to 14, and 5 to 12.');
    figure(1);
  else
    fprintf('Nothing received.\n');
  end
  if debugging
  % fprintf('TestClearMex once crashed at line 269.\n');
    TestClearMex(daq);
  end

  % DaqAInScan
  fprintf('\nDaqAInScan: sampling analog input.\n');
  options.lowChannel=[];
  options.highChannel=[];
  options.count=1000;
  options.f=2000;
  options.immediate=0;
  options.trigger=0;
  options.print=0;
  options.channel=0:0;
  options.range=3*ones(size(options.channel));
  c=length(options.channel);
  % n is sample/channel/report
  if options.immediate
    n=1;
  else
    n=31/c;
  end
  start=GetSecs;
  [data,params]=DaqAInScan(daq(1),options);
  stop=GetSecs;
  fprintf('Got %d (of %d) sample/channel on %d channels at %.0f Hz.\n',...
      size(data,1),options.count,size(data,2),params.fActual);
  if length(params.times)>1
    t=params.times;
    fprintf('Received %.1f report/s, %.1f sample/channel/s.\n',...
        (length(t)-1)/(t(end)-t(1)),(size(data,1)-n)/(t(end)-t(1)));
  end
  if debugging
  % fprintf('TestClearMex once crashed at line 302.\n');
    TestClearMex(daq);
  end

  % DaqAInScanBegin, DaqAInScanContinue, DaqAInScanEnd
  % Works well for f up to 2048/c sample/channel/s, where c is number of
  % channels. Currently (18 April 2005) unreliable at higher rates.
  c=length(options.channel);
  for log2f=11
    options.f=2^log2f/c;
    fprintf('\nDaqAInScanBegin, DaqAInScanContinue, DaqAInScanEnd: sampling analog input. \n');
    duration=1;
    options.count=duration*options.f;
    options.immediate=0;
    params=DaqAInScanBegin(daq(1),options);
    params=DaqAInScanContinue(daq(1),options);
    params=DaqAInScanContinue(daq(1),options);
    [data,params]=DaqAInScanEnd(daq(1),options);
    fprintf('Got %d (of %d) sample/channel on %d channels at %.0f Hz.\n',size(data,1),options.count,size(data,2),params.fActual);
    if length(params.times)>1
      t=params.times;
      c=size(data,2);
      % n is sample/channel/report
      if options.immediate
        n=1;
      else
        n=31/c;
      end
      fprintf('Received %.1f report/s, %.1f sample/channel/s.\n',(length(t)-1)/(t(end)-t(1)),(size(data,1)-n)/(t(end)-t(1)));
    end
  end
  if debugging
  %	fprintf('TestClearMex once crashed at line 390.\n');
    TestClearMex(daq);
  end

  % DaqAOut & DaqAInScan: 4 Hz sinewave
  % This runs well at slow sampling rates (100 Hz). Attempting to run at high
  % rates (e.g. 1000 Hz) results in losing most of the data. This isn't a
  % bug. It's asking the USB-1208FS to do two things at once (AOut and
  % AInScan) and clearly they interfere with each other. None of the
  % Measurement Computing literature that I've read mentions the issue of
  % doing two things at once, so there's no promise to live up to. This
  % simultaneous in and out is an excellent way to test the capabilities of
  % the USB-1208FS without any extra equipment, but is probably not a useful
  % model for experimental work since it limits you to low sampling rates. If
  % you need to sample in and out at the same time you may want to buy two
  % USB-1208FS units and use one for input and the other for output.
  f=1;
  fprintf([
      '\nDaqAOut & DaqAInScan: producing %.0f Hz sinewave and square wave output\n'...
      'voltages, on two channels, and reading them back in through the analog inputs. \n'...
      'We plot the readings in Figure 2. (It''s just noise unless you''ve installed\n'...
      'wires connecting output to input.)\n'],f);
  time=0:0.02:5;
  x=f*2*pi*time;
  sineWave=0.5+0.5*sin(x);       % Raised sine. Positive.
  triangleWave=0.5+0.5*trin(x);  % Raised triangle. Positive.
  squareWave=round(sineWave);
  % In
  v0=[];
  v1=[];
  options.f=100;
  options.channel=[];
  options.range=[];
  options.lowChannel=0;
  options.highChannel=0;
  options.count=round(max(time)*options.f);
  options.immediate=0;
  channel=options.lowChannel:options.highChannel;
  range=3*ones(size(channel));
  for i=channel
    DaqAIn(daq(1),i,3);% set gain range
  end
  start=GetSecs;
  params=DaqAInScanBegin(daq(1),options);
  for i=1:length(time)
    WaitSecs(time(i)+start-GetSecs);
    err=DaqAOut(daq(1),0,sineWave(i));
    err=DaqAOut(daq(1),1,squareWave(i));
    if err.n
      break;
    end
    tOut(i)=GetSecs-start;
  end
  params=DaqAInScanContinue(daq(1),options);
  [data,params]=DaqAInScanEnd(daq(1),options);
  fprintf('Got %.0f (of %.0f) sample/channel on %d channels at %.0f Hz.\n',...
    size(data,1),options.count,size(data,2),params.fActual);
  if ~isempty(data)
    t=(1:size(data,1))/params.fActual;
    v0=data(:,1);
    figure(2);
    plot(t,v0,'r');
    if size(data,2)>=2
      v1=data(:,2);
      hold on
      plot(t,v1,'g');
      hold off
      title(sprintf('%.0f Hz sine & square waves put out by DaqAOut and read back in by DaqAInScan.',f));
    else
      title(sprintf('%.0f Hz sine wave put out by DaqAOut and read back in by DaqAInScan.',f));
    end
    ylabel('Volts');
    xlabel('Time (s)');
  end
  if debugging
    TestClearMex(daq);
  end

  % DaqAOutScan. Analog output scan.
  % Works well for f up to 1024 sample/channel/s on one channel, and 256
  % sample/channel/s on two channels. Currently (28 April 2005) unreliable at
  % higher rates.
  for log2f=10
    options.f=2^log2f; % sampling frequency in Hz
    duration=0.999; % s
    fSine=10; % Hz
    options.lowChannel=0;
    options.print=0;
    outTick=1/options.f; % s
    wave=0.5+0.5*sin(fSine*2*pi*(0:outTick:duration)); % Raised sine. Positive.
    if 1
      % works for f up to 1024
      options.highChannel=0;
    else
      % works for f up to 256
      options.highChannel=1;
      wave=[wave' wave'];
    end
    options.getReports=1;
    c=1+options.highChannel-options.lowChannel;
    fprintf('\nDaqAOutScan: producing %.0f Hz sine for %.0f s sampled at %.0f Hz on %d channels.\n',...
      fSine,duration,options.f,c);
    params=DaqAOutScan(daq(1),wave,options);
    if isempty(params.start)
      params.start=nan;
    end
    if isempty(params.end)
      params.end=nan;
    end
    fprintf('Sent %.0f (out of %.0f) samples/channel on %d channels in %.0f (out of %.0f) ms.\n',...
      params.countActual,length(wave),c,1000*(params.end-params.start),1000*length(wave)/options.f);
    r=(params.numberOfReportsSent-1)/(params.end-params.start);
    fprintf('Sending speed was %.0f report/s, %.0f sample/channel/s.\n',r,r*32/c);
  end
  if debugging
  %	fprintf('TestClearMex once crashed at line 499.\n');
    TestClearMex(daq);
  end

  % DaqALoadQueue.
  fprintf('\nDaqALoadQueue: setting channel 0 to gain range 0.\n');
  err=DaqALoadQueue(daq(1),0,0);
  if debugging
    TestClearMex(daq);
  end
end % Is1608; else (DaqAOut tests)

waitsecs(0.2);

fprintf('\n** COUNTER COMMANDS \n** DaqCIn, DaqCInit\n');

% DaqCIn. Reading counter
fprintf('\nDaqCIn: reading the counter.\n');
count=DaqCIn(daq(1));
if ~isempty(count)
    fprintf('Count is %d.\n',count);
else
    fprintf('Nothing received.\n');
end

if Is1608
  IShouldTestCounter = TwoStateQuery('If you would like to test the counter, make sure pin 21 is connected to pin 38.  Then click "Yes".');
  if IShouldTestCounter > 0
    DaqCInit(daq);
    StartCount = DaqCIn(daq);
    if StartCount
      error('Counter did not reset to zero.  Sorry!');
    end
    DaqDConfigPortBit(daq,0,0);
    for k=1:150
      DaqDWriteBit(daq,0,1);
      DaqDWriteBit(daq,0,0);
    end
    EndCount = DaqCIn(daq);
    if EndCount ~= 150
      fprintf(sprintf('Counter reads %d when it should read 150!  Oops!',EndCount));
      if abs(EndCount-150) > 1
        error('In my tests, some times one count was missed, so I''ll accept that, but...');
      else
        fprintf(['\nUsually my counts were exact, but some times I missed one, particularly if I ran\n' ...
                 'the square wave test.  We''ll call this a pass, but just barely.  Moving on...\n\n']);
      end
    else
      fprintf('\nOne hundred and fifty pulses sent to the counter, 150 pulses counted.  Moving on...\n\n');
    end
  end
end % if Is1608
    

if debugging
    TestClearMex(daq);
end

% DaqCInit. Resetting counter to zero.
fprintf('\nDaqCInit: resetting counter to zero.\n');
err=DaqCInit(daq(1));

% I wrote my own versions of these above before I got down here and realized
% Denis wrote tests of these functions too...  I "if 0"d most of the code below, 
% but in the indicated places, it was like that when I got here -- mpr
%
% fprintf(['\n** MISCELLANEOUS COMMANDS \n** DaqGetStatus, DaqSetCal, DaqSetSync, DaqSetTrigger\n']);


% Denis had this test here (and had DaqBlinkLED listed in the fprintf that
% immediately precedes this), but it made more sense to me to test this up
% top and use DaqBlinkLED as a way for users to choose which device to test
% if they have more than one. I recommend using my code for this function since 
% I do more with it in my tests.  -- mpr
if 0
  % DaqBlinkLED
  fprintf('\nDaqBlinkLED: blinking the LED.\n');
  err=DaqBlinkLED(daq(1));
end

if 0 % This was commented out before I got here -- mpr
    % DaqReset. Optional reset. Make sure the USB-1208FS is "attached". In
    % theory it's nice to detect anomalous behavior and fix it, by
    % resetting the device. However, this requires a call to CLEAR PsychHID to
    % re-enumerate, which may result in a crash when you next ask PsychHID to 
    % receive reports. Don't use DaqReset. Quitting and restarting MATLAB is a 
    % reliable way of reestablishing normal communication with the USB-1208FS.
    err=PsychHID('SetReport',daq(1),2,64,uint8(64)); % Blink LED
    if streq(err.name,'kIOReturnNotAttached')
        fprintf('\nMac OS error message says %s is "not attached". But we know it is.\n',devices(daq(1)).product);
        fprintf('We will attempt to reestablish communication by re-enumerating, resetting the USB, and re-enumerating again. ');
        err=DaqReset(daq(1));
        fprintf('End of reset. Hopefully your %s is working again.\n',devices(daq(1)).product);
    end
end

if 0
  for i=[1 0]
      % DaqSetSync
      fprintf('\nDaqSetSync: configure synchronization to %d. (0 for master, 1 or 2 for slave)\n',i);
      err=DaqSetSync(daq(1),i);

      % DaqGetStatus
      fprintf('\nDaqGetStatus: reading the status bits.\n');
      status=DaqGetStatus(daq(1));
      if ~isempty(status)
          if status.master
              fprintf('master.\n');
          else
              fprintf('slave.\n');
          end
      else
          fprintf('Nothing received.\n');
      end
  end
  if debugging
      TestClearMex(daq);
  end

  if Is1608
    fprintf(['\nYou can test the calibration if you want; but I didn''t see a point\n' ...
             'to the test that was run before.  It set the calibration voltage for one\n' ...
             'second, but didn''t even tell you the pins until it was testing them.  Note\n' ...
             'the pins are different (CAL pin is pin 17 (with pin 16 being the nearest\n' ...
             'ground) in the 1608FS.  If you want to monitor the voltage across these\n' ...
             'pins, go ahead and run the test at "DaqSetCal".  I think the function\n' ...
             'should work as is, but I have not tested it.  -- mpr \n\n']);
  else
    % DaqSetCal
    fprintf(['\nDaqSetCal: setting calibration voltage output to +2.5 V for 1 s. \n'...
        'CAL is pin 16; pin 15 is ground.\n']);
    err=DaqSetCal(daq(1),1); % SetCal +2.5 V
    WaitSecs(1);
    err=DaqSetCal(daq(1),0); % SetCal 0 V

    % DaqSetTrigger
    fprintf('\nDaqSetTrigger: setting to trigger on falling edge.\n');
    err=DaqSetTrigger(daq(1),0);
  end % if Is1608; else
end % if 0
  
% Denis originally tested DaqMemRead here, but I moved the test up front because
% it does not depend upon the wiring of the terminals.  Hence it is a more
% stringent test; if it fails, it seems to me there is no reason to test
% anything else.  This is another test I recommend you stick with my code 
% instead of reverting.-- mpr
if 0
  fprintf(['\n** MEMORY COMMANDS\n'...
      '** DaqMemRead, DaqMemWrite, DaqReadCode, DaqPrepareDownload, DaqWriteCode,\n'...
      '** DaqWriteSerialNumber\n']);
  fprintf(['\nWe only test the two read commands, since the write commands could\n'...
      'potentially screw up the firmware, and we have no immediate need for\n'...
      'writing to memory.\n']);
  if debugging
      TestClearMex(daq);
  end

  % DaqMemRead
  fprintf('\nDaqMemRead: Reading memory.\n');
  data=DaqMemRead(daq(1),hex2dec('100'),62);
  if isempty(data)
      fprintf('Nothing received.\n');
  end
end

% This is another test that seems pretty pointless to me.  It might work as is,
% but if you don't put code in, how can you know what should be there?  The fact
% that *something* is received is not a terribly stringent test.  My guess is
% that if anyone wants to use this function, they'll devise their own tests of
% it, and the tests will be a good deal more meaningful than this.  I don't feel
% a need to use the function at the moment, so I'm bailing on writing that code.
%  -- mpr
if 0
  % DaqReadCode
  fprintf('\nDaqReadCode: Reading program memory.\n');
  data=DaqReadCode(daq(1),0,62);
  if isempty(data)
      fprintf('Nothing received.\n');
  end
  if debugging
      TestClearMex(daq);
  end
end

% The following was in Denis's original version; his comment is now incorrect
% because this function is tested above.  I leave this here for posterity in
% case anyone wants to revert to Denis's version. -- mpr
if 0
    % NOT TESTED. I don't need these functions, which write to memory, and
    % I don't want to risk screwing up my USB-1208FS firmware. If you decide to
    % try this, pick your addresses carefully, after consulting the table
    % of memory types: "help daqwritecode".

    % DaqMemWrite
    fprintf('\nDaqMemWrite: Writing memory.\n');
    err=DaqMemWrite(daq(1),0,1:2);

    % DaqPrepareDownload
    fprintf('\nDaqPrepareDownload: Preparing for program memory download.\n');
    err=DaqPrepareDownload(daq(1));

    % DaqWriteCode
    fprintf('\nDaqWriteCode: Writing program memory.\n');
    err=DaqWriteCode(daq(1),0,1:2);
end

% My history here was a bit odd... My recollection is that the first time I ran
% PsychHID('Devices'), the serial number reported for my USB-1608FS was 0.  I
% ran DaqWriteSerialNumber and tried to get the value set correctly.  I wasn't
% sure it worked, but later I found that the value was set (except that the
% documentation for my device has a 9-character serial number and the number is
% truncated to eight characters.  Nevertheless, I am with Denis that it is
% probably unwise to rewrite your serial number unless you absolutely know you
% need to.  So I leave this functionally commented out. -- mpr
if 0
    % WARNING: you probably do NOT want to run this command, because it
    % will over-write your factory-assigned serial number. I tested this
    % on my USB-1208FS and it works fine. Note that the new serial number
    % won't show up until you unplug and reconnect your device.

    % DaqWriteSerialNumber
    serialString='00000123';
    err=DaqWriteSerialNumber(daq(1),serialString);
    fprintf('\nDaqWriteSerial: setting the serial number to "%s".\n',serialString);
end

if Is1608
end


fprintf('\nDone.\n');

function y=trin(x)
% y=trin(x)
% Triangle wave. Has same peaks as SIN, but is linear between those peaks.
y=4*mod(x/2/pi,1);
fy=floor(y);
i=find(fy==1 | fy==2);
y(i)=2-y(i);
i=find(fy==3);
y(i)=y(i)-4;
return

function TestClearMex(daq)
% TestClearMex is being used by dgp to track down a crash of PsychHID associated
% with CLEAR MEX. 
options.printCrashers=1;
% PsychHID('ReceiveReports',daq(1),options);
% 
% % DaqDIn
% fprintf('\nDaqDIn: reading digital ports.\n');
% data=DaqDIn(daq(1));
% if ~isempty(data)
%     fprintf('DaqDIn: %3d %3d.\n',data);
% else
%     fprintf('DaqDIn: Nothing received.\n');
% end

fprintf('CLEAR MEX\n');
clear mex;

PsychHID('ReceiveReports',daq(1),options);

% DaqDIn
fprintf('DaqDIn: reading digital ports.\n');
data=DaqDIn(daq(1));
if ~isempty(data)
    fprintf('DaqDIn: %3d %3d.\n',data);
else
    fprintf('DaqDIn: Nothing received.\n');
end
return