File: DaqAIn.m

package info (click to toggle)
psychtoolbox-3 3.0.9%2Bsvn2579.dfsg1-1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 63,408 kB
  • sloc: ansic: 73,310; cpp: 11,139; objc: 3,129; sh: 1,669; python: 382; php: 272; makefile: 172; java: 113
file content (173 lines) | stat: -rw-r--r-- 6,677 bytes parent folder | download
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
function v=DaqAIn(daq,channel,range,UnCal)
% v=DaqAIn(DeviceIndex,channel,range,[DoNotCalibrate])
% Analog input.
% USB-1208FS:
% "v" is the measured voltage, in Volts, or NaN if no data were received.
% "DeviceIndex" is a small integer, the array index specifying which HID
%     device in the array returned by PsychHID('Devices') is interface 0
%     of the desired Daq device.
% "channel" (0 to 15) selects any of various single-ended or differential 
%     measurements.
%     "channel" Measurement
%      0        0-1 (differential)
%      1        2-3 (differential)
%      2        4-5 (differential)
%      3        6-7 (differential)
%      4        1-0 (differential)
%      5        3-2 (differential)
%      6        5-4 (differential)
%      7        7-6 (differential)
%      8          0 (single-ended)
%      9          1 (single-ended)
%     10          2 (single-ended)
%     11          3 (single-ended)
%     12          4 (single-ended)
%     13          5 (single-ended)
%     14          6 (single-ended)
%     15          7 (single-ended)
% "range" (0 to 7) sets the gain (hence voltage range):
%     for single-ended measurements (channels 8-15), range is always +/- 10 V,
%     and attempts to set ranges other than 0 usually result in saturation, so
%     setting range in this function does not do anything.  For differential
%     measurements (channels 0-7), the map between range as input to this
%     function and the output generated is:
%     0 for Gain 1x (+/-20 V),   1 for Gain 2x (+/-10 V),
%     2 for Gain 4x (+/-5 V),    3 for Gain 5x (+/-4 V),
%     4 for Gain 8x (+/-2.5 V),  5 for Gain 10x (+/-2 V),
%     6 for Gain 16x (+/-1.25 V),  7 for Gain 20x (+/-1 V).
% "DoNotCalibrate" for 1208FS has no effect
%
% USB-1608FS:
% only single-ended inputs are defined, so "channel" is restricted to integers
% from 0 to 7.  Ignore the manual which claims that gains are restricted to only
% four possible values.  Thank the linux people for discovering:
%      0 for Gain 1x (+/- 10 V),      1 for Gain 2x (+/-5 V),
%      2 for Gain 4x (+/- 2.5 V),     3 for Gain 5x (+/- 2 V),
%      4 for Gain 8x (+/- 1.25 V),    5 for Gain 10x (+/- 1V),
%      6 for Gain 16x (+/- 0.625 V),  7 for Gain 32x (+/- 0.3125 V)
%
% "DoNotCalibrate" (0 or 1) if non-zero, function does not use information
% acquired from calibration measurements (see DaqCalibrateAIn).  This should
% probably always be 0 when function is called by a user (hence it defaults to
% 0).  Flag was created for the purpose of acquiring calibration data.
% Otherwise subsequent calibration measurements would be fits of fits.
%
% See also Daq, DaqFunctions, DaqPins, DaqTest, PsychHIDTest,
% DaqDeviceIndex, DaqDIn, DaqDOut, DaqAIn, DaqAOut, DaqAInScan,DaqAOutScan.
%
% 4/15/05 dgp Wrote it.
% 1/21/07 asg changed normalization value from 2^16 to 2^15 to account for 16th bit as a sign bit (not data bit)
%             and modified the "range" value help.
% 6/17/07 mk  Add proper sign handling for negative voltages.
% 12/2x/07-1/x/08  mpr   modified to work with USB-1608FS and changed some
%                           terminology; particularly did away with "sign" name
%                           conflict ("sign" is a Matlab function)

devices = PsychHID('Devices');

if nargin < 4 || isempty(UnCal)
  UnCal=0;
end

if strcmp(devices(daq).product(5:6),'16')
  Is1608=1;
  MaxChannelID = 7;
else
  Is1608=0;
  MaxChannelID = 15;
  % ignore range input for single-ended measurements
  if channel > 7
    range=0;
  end
end

err1=PsychHID('ReceiveReports',daq);
err2=PsychHID('ReceiveReportsStop',daq);
[reports,err]=PsychHID('GiveMeReports',daq);
if ~ismember(channel,0:MaxChannelID)
    error(sprintf('DaqAIn: "channel" must be an integer 0 to %d.',MaxChannelID));
end
if ~ismember(range,0:7)
    error('DaqAIn: "range" must be an integer 0 to 7.');
end
err3=PsychHID('SetReport',daq,2,16,uint8([16 channel range])); % Read analog input
if err.n
    fprintf('DaqAIn SetReport error 0x%s. %s: %s\n',hexstr(err.n),err.name,err.description);
end
err4=PsychHID('ReceiveReports',daq);
[report,err5]=PsychHID('GetReport',daq,1,16,3); % Get report

if err.n
    fprintf('DaqAIn GetReport error 0x%s. %s: %s\n',hexstr(err.n),err.name,err.description);
end
err6=PsychHID('ReceiveReportsStop',daq);

if length(report)==3
  if Is1608
    vmax = [10 5 2.5 2 1.25 1 0.625 0.3125];

    RawValue = double(report(3))*256 + double(report(2));
    v = vmax(range+1)*(RawValue/32768-1);
    if UnCal
      return; 
    else
      DaqPrefsDir = DaqtoolboxConfigDir;
      if exist([DaqPrefsDir filesep 'DaqPrefs.mat'],'file')
        DaqVars = load([DaqPrefsDir filesep 'DaqPrefs']);
        if isfield(DaqVars,'CalData')
          CalData = DaqVars.CalData;
          GoodIndices = find(CalData(:,1) == channel & CalData(:,2) == range);
          if ~isempty(GoodIndices)
            TheDays = CalData(GoodIndices,end);
            ThisDay = datenum(date);
            [DaysSinceLast,BestIndex] = min(ThisDay-TheDays);
            AllThatDay = find(TheDays == TheDays(BestIndex));
            MostRecentPolyFit = CalData(GoodIndices(AllThatDay(end)),3:5);

            if DaysSinceLast > 30
              warning(sprintf('Calibration of this channel has not been performed since %s!!', ...
                      datestr(TheDays(BestIndex))));
            end

            v = polyval(MostRecentPolyFit,v);
            return;
          end
        end % if isfield(DaqVars,'CalData')
      end % if exist([DaqPrefsDir filesep 'DaqPrefs.mat'],'file')
    end % if UnCal
      
    warning(sprintf(['It looks like this channel has not yet been calibrated.  In my\n' ...
                     'tests, uncalibrated values could be off by as much as 15%%!']));
  else
    % Mapping table value -> voltage for differential gains:
    vmax=[20 10 5 4 2.5 2 1.25 1];

    RawReturn = double(report(2:3))*[1; 256];
    if channel < 8
      % combined two-bytes of report make a 2's complement 12-bit value
      DigitalValue = bitshift(RawReturn,-4);
      if bitget(DigitalValue,12)
        DigitalValue = -bitcmp(DigitalValue,12)-1;
      end
    else
      % range needs to be zero above during call to PsychHID('SetReport',... but
      % must be 1 to get scale below.
      range=1;
      % combined two-bytes of report make a 2's complement 11-bit value
      if RawReturn > 32752
        DigitalValue = -2048;
      elseif RawReturn > 32736
        DigitalValue = 2047;
      else
        DigitalValue = bitand(4095,bitshift(RawReturn,-3))-2048;
      end
    end
    
    v=vmax(range+1)*DigitalValue/2047;
  end    
else
%   fprintf('length(report) %d\n',length(report));
    v=NaN;
end

return;