This file is indexed.

/usr/share/psychtoolbox-3/PsychVideoCapture/PsychCamSettings.m is in psychtoolbox-3-common 3.0.11.20131230.dfsg1-1build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
function rc = PsychCamSettings(cmd, grabber, varargin)
% rc = PsychCamSettings(cmd, grabber [, arg0, arg1, ...])
%
% Setup tool for video sources for use with Psychtoolbox
% video capture functions. This function can mostly only operate
% on IIDC/DCAM machine vision standard compliant camera connected
% via IEEE1394-Firewire bus or USB bus + IIDC protocol. In other
% words, it only operates on cameras controlled via the libdc1394
% firewire video capture engine on Linux and OSX, not on standard
% consumer/prosumer class cameras controlled by the GStreamer engine,
% e.g., webcams, DV cameras etc.
%
% PsychCamSettings is used to query or change settings of such
% a video source that is supported by the Screen() subfunctions
% for video capture. The first parameter, a 'cmd' command string
% specifies the subfunction to execute. The second parameter
% 'grabber' is the device handle returned by Screen('OpenVideoCapture').
% All following parameters are dependent on the selected subfunction.
%
% Subfunctions of form 'XXX' change the setting of a parameter XXX.
% Subfunctions of form 'XXX' query the current setting of a parameter XXX.
% Subfunctions of form 'AutoXXX' try to switch parameter XXX into automatic
% control, if supported by the camera or video source.
%
% The type of parameters supported is highly dependent on the specific video
% source. Unsupported parameters are usually "no operations" - silently ignored.
%
% For known camera models, the tool will try to map physically meaningful
% values into camera settings and return camera settings as meaningful properties.
% E.g., exposure time is expected and returned in milliseconds, if the mapping
% for the specific camera is known. Otherwise it is set and returned in arbitrary
% units.
%
% Currently known cameras: Basler A602f grayscale firewire camera. Unibrain Fire-i
% firewire camera.
%
% Parameters and their meaning:
%
% curval = PsychCamSettings('ExposureTime', grabber, val)
% -- Set and/or return current exposure time in milliseconds for supported cams, and
% in raw camera specific system units for unknown cameras.
%
% curval = PsychCamSettings('Brightness', grabber, val)
% -- Set/Return brightness setting in arbitrary units. Brightness is the DC offset
% added to the CCD sensor signal before amplification and A/D conversion.
%
% curval = PsychCamSettings('Gain', grabber, val)
% -- Set/Return gain setting in arbitrary units. Gain is the multiplier
% applied to the CCD sensor signal during amplification and before A/D conversion.
%
% curval = PsychCamSettings('Gamma', grabber, val)
% -- Set/Return gamma setting. Gamma is used to influence or set gamma correction.
%
% curval = PsychCamSettings('Sharpness', grabber, val)
% -- Set/Return sharpness setting in arbitrary units. Manipulates digital post-
% processing of images in the camera.
%
% curval = PsychCamSettings('WhiteBalance', grabber, val)
% -- Set/Return white-balance setting in arbitrary units. Only meaningful on color cams.
%
% curval = PsychCamSettings('Saturation', grabber, val)
% -- Set/Return color saturation setting in arbitrary units. Only meaningful on color cams.
%
% Similar to above are queries and (auto-)settings for: Hue, WhiteShading, Iris, Focus, Pan, Tilt,
% Zoom, CaptureQuality, CaptureSize, Temperature, FrameRate, OpticalFilter and TriggerDelay.
%
% curval = PsychCamSettings('BacklightCompensation', grabber, val)
% -- Set/Return setting for backlight compensation mode. Backlight compensation is active
% if control of exposure time, gain and brightness are switched to automatic. It defines
% the algorithm to use for computing the overall image brightness. This is currently
% only supported on the Unibrain Fire-i camera and has the following meaning:
%
% 0 = Off. Just average across image.
% 1 = Use a disc in the center of the image.
% 2 = Use some weighted mix of a disc in the image center and the area outside the disc.
% 3 = Use some portrait mode for optimal exposure of a person sitting in front of the cam.
% 4 = Use upper third of image.
% 5 = Use middle third of image.
% 6 = Use lower third of image.
%
% Special commands and their meaning:
%
% vendor = PsychCamSettings('GetVendor', grabber) 
% -- Return camera vendor name string.
%
% model = PsychCamSettings('GetModel', grabber) 
% -- Return camera model name string.
%
% known = PsychCamSettings('IsKnownCamera', grabber)
% -- Return 1, if this camera is known to PsychCamSettings,
% so it can accept and return meaningful physical properties,
% instead of unknown device units.
%
% settings = PsychCamSettings('AutomateAllSettings', grabber)
% -- Switch all settings into automatic control mode, where possible,
% and return the current settings in a struct.
%
% settings = PsychCamSettings('GetAllSettings', grabber)
% -- Return all known settings in a struct.
%
% oldsettings = PsychCamSettings('SetAllSettings', grabber, settings)
% -- Set all settings from a struct 'settings'.
%
% latency = PsychCamSettings('EstimateLatency', grabber [, fps])
% -- This command analyses the current camera settings and, based on
% the specification of the camera, tries to estimate the latency (in
% seconds) between start of exposure of a video frame and arrival of
% the video frame in the computers video buffer.
%
% If you subtract this 'latency' value from the 'capturetimestamp'
% returned by the Screen('GetCapturedImage') function, you should
% get an estimate of when (in system time) the image was
% actually acquired that corresponds to the captured image.
%
% Please note: In theory Basler firewire cameras with "SFF cycle timer support"
% should be able to report the start time of image exposure directly via
% the returned capture timestamps if the command ...
% Screen('SetVideoCaptureParameter', grabber, 'BaslerFrameTimestampEnable');
% ... was executed before start of capture, therefore making this 'EstimateLatency'
% dance redundant. In practice though, the two tested Basler cameras which should
% support this feature didn't work properly, ie., they returned completely bogus
% capture timestamps when 'BaslerFrameTimestampEnable' was called. Your mileage
% may therefore vary, but it is at least worth a try if you possess a Basler camera.
% 
% Latency is defined as:
%
% Duration of sensor-exposure + sensor readout delay + transmission
% onset delay + time needed for data transfer over Firewire bus or
% other device.
%
% The latency values computed here are based on the official camera
% specs. If the spec is wrong or inaccurate, then this value will
% be wrong or inaccurate as well, so use with caution!
%

% History:
% 20.06.2006 Written (MK).
% 25.12.2013 Updated for support of Basler A312fc and more parameters.

if nargin < 1 || isempty(cmd)
   error('No subcommand specified!');
end

if nargin < 2 || isempty(grabber)
   error('No grabber handle provided!');
end

% Query model and vendor, match it against our camlist:
vendor = Screen('SetVideoCaptureParameter', grabber, 'GetVendorname');
model  = Screen('SetVideoCaptureParameter', grabber, 'GetModelname');
rc = model;

% Check for Unibrain Fire-i...
if ~isempty(strfind(vendor, 'Unibrain')) && ~isempty(strfind(model, 'Fire-i'))
   IsFirei = 1;
else
   IsFirei = 0;
end

% Check for Basler A602f...
if ~isempty(strfind(vendor, 'Basler')) && ~isempty(strfind(model, 'A602f'))
   IsA602f = 1;
else
   IsA602f = 0;
end

% Check for Basler A312fc...
if ~isempty(strfind(vendor, 'Basler')) && ~isempty(strfind(model, 'A312fc'))
   IsA312fc = 1;
else
   IsA312fc = 0;
end

if strcmp(cmd, 'GetVendor')
     rc = vendor;
     return;
end

if strcmp(cmd, 'GetModel')
     rc = model;
     return;
end

if strcmp(cmd, 'IsKnownCamera')
     % Return 1, if this camera is known to the script.
     rc = IsFirei || IsA602f || IsA312fc;
     return;
end

if strcmp(cmd, 'EstimateLatency')
     % Estimate the latency from start of exposure to the point in time,
     % when the captured frame has finally fully arrived in system memory.
     % One can compute real start of frame acquisition by subtracting this
     % latency value from the capturetimestamp that is returned by
     % Screen('GetCapturedImage').

     % Latency is the sum of exposure time + transmission start delay +
     % transmission time.

     % Transmission time is defined by the IEEE-1394 firewire standard as
     % 1.0 secs / captureframerate:
     if nargin < 3
        % No hypothetical framerate specified. Query it from system.
        t_transmission = 1.0 / Screen('SetVideoCaptureParameter', grabber, 'GetFramerate');
     else 
        % Use provided value instead of querying real setting.
        t_transmission = 1.0 / varargin{1};
     end

     % Transmission onset delay and exposuretime are camera specific and
     % need to handled therefore by camera.
     
     % If we do not know the camera, then we do not know the real exposure time.
     % We just assume zero exposure time and a generic transmission delay of
     % 1 firewire bus cycle at 400 Mbit, which is a good guess:
     t_transdelay = 0.000125;
     t_exposure = 0;

     if IsFirei
        % We do not know the real transmission delay of Fire-i for sure, but
        % as the transmission time of Fire-i is at least 33.33 ms at maximum framerate,
        % and sensor readout time is probably much less, even at maximum ROI, it is
        % reasonable to assume that we have the standard delay of 125 microseconds.
        % Therefore, we leave transdelay at its default and just query exposure time.
        t_exposure = DoFireICamExposureTime(grabber, []) / 1000.0;
     end

     if IsA602f
        % Exposure can be queried.
        t_exposure = DoA602fCamExposureTime(grabber, []) / 1000.0;

        % Transmission delay depends on relative duration of transmission time and
        % sensor readout time. It is calculated as (ROIheight+3)*15.28 microseconds.
        readout_time = (RectHeight(Screen('SetVideoCaptureParameter', grabber, 'GetROI')) + 3);
        readout_time = readout_time * 0.00001528;

        if t_transmission > readout_time
            % Transmission delay is 125 microseconds.
            t_transdelay = 0.000125;
        else
            % Transmission delay is this.
            t_transdelay = (readout_time - t_transmission) + 0.000125;
        end
     end

     if IsA312fc
        % Exposure can be queried.
        t_exposure = DoA312fcCamExposureTime(grabber, []) / 1000.0;

        % Transmission delay depends on relative duration of transmission time and
        % sensor readout time. It is calculated as ROIheight * 28.27 microseconds
        % + 2178 usecs.
        readout_time = RectHeight(Screen('SetVideoCaptureParameter', grabber, 'GetROI'));
        readout_time = readout_time * 0.00002827 + 0.002178;

        if t_transmission > readout_time
            % Transmission start delay is 125 microseconds.
            t_transdelay = 0.000125;
        else
            % Transmission delay is this.
            t_transdelay = (readout_time - t_transmission) + 0.000125;
        end
     end
     
     % Ok, final result:
     tdelay = t_exposure + t_transdelay + t_transmission;

     % Return value.
     rc = tdelay;
     return;
end

if strcmp(cmd, 'AutomateAllSettings')
     % Switch all settings to Auto control mode if possible, return current settings.
     rc.brightness = Screen('SetVideoCaptureParameter', grabber, 'AutoBrightness');
     rc.gain = Screen('SetVideoCaptureParameter', grabber, 'AutoGain');
     rc.shutter = Screen('SetVideoCaptureParameter', grabber, 'AutoShutter');
     rc.exposure = Screen('SetVideoCaptureParameter', grabber, 'AutoExposure');
     rc.sharpness = Screen('SetVideoCaptureParameter', grabber, 'AutoSharpness');
     [rc.whitebalance1, rc.whitebalance2] = Screen('SetVideoCaptureParameter', grabber, 'AutoWhiteBalance');
     [rc.whiteshadingR, rc.whiteshadingG, rc.whiteshadingB] = Screen('SetVideoCaptureParameter', grabber, 'AutoWhiteShading');
     rc.saturation = Screen('SetVideoCaptureParameter', grabber, 'AutoSaturation');
     rc.gamma = Screen('SetVideoCaptureParameter', grabber, 'AutoGamma');
     rc.vendor = Screen('SetVideoCaptureParameter', grabber, 'GetVendorname');
     rc.model = Screen('SetVideoCaptureParameter', grabber, 'GetModelname');
     rc.hue = Screen('SetVideoCaptureParameter', grabber, 'AutoHue');
     rc.iris = Screen('SetVideoCaptureParameter', grabber, 'AutoIris');
     rc.Focus = Screen('SetVideoCaptureParameter', grabber, 'AutoFocus');
     rc.Zoom = Screen('SetVideoCaptureParameter', grabber, 'AutoZoom');
     rc.Pan = Screen('SetVideoCaptureParameter', grabber, 'AutoPan');
     rc.Tilt = Screen('SetVideoCaptureParameter', grabber, 'AutoTilt');
     rc.OpticalFilter = Screen('SetVideoCaptureParameter', grabber, 'AutoOpticalFilter');
     rc.CaptureSize = Screen('SetVideoCaptureParameter', grabber, 'AutoCaptureSize');
     rc.CaptureQuality = Screen('SetVideoCaptureParameter', grabber, 'AutoCaptureQuality');
     rc.FrameRate = Screen('SetVideoCaptureParameter', grabber, 'FrameRate'); % Auto makes no sense.
     rc.TriggerDelay = Screen('SetVideoCaptureParameter', grabber, 'TriggerDelay'); % Auto makes no sense.
     rc.Temperature = Screen('SetVideoCaptureParameter', grabber, 'AutoTemperature');
     return;
end

if strcmp(cmd, 'GetAllSettings')
     % Read out all known settings and store them in returned struct:
     rc.brightness = Screen('SetVideoCaptureParameter', grabber, 'Brightness');
     rc.gain = Screen('SetVideoCaptureParameter', grabber, 'Gain');
     rc.shutter = Screen('SetVideoCaptureParameter', grabber, 'Shutter');
     rc.exposure = Screen('SetVideoCaptureParameter', grabber, 'Exposure');
     rc.sharpness = Screen('SetVideoCaptureParameter', grabber, 'Sharpness');
     [rc.whitebalance1, rc.whitebalance2] = Screen('SetVideoCaptureParameter', grabber, 'WhiteBalance');
     [rc.whiteshadingR, rc.whiteshadingG, rc.whiteshadingB] = Screen('SetVideoCaptureParameter', grabber, 'WhiteShading');
     rc.saturation = Screen('SetVideoCaptureParameter', grabber, 'Saturation');
     rc.gamma = Screen('SetVideoCaptureParameter', grabber, 'Gamma');
     rc.vendor = Screen('SetVideoCaptureParameter', grabber, 'GetVendorname');
     rc.model = Screen('SetVideoCaptureParameter', grabber, 'GetModelname');
     rc.hue = Screen('SetVideoCaptureParameter', grabber, 'Hue');
     rc.iris = Screen('SetVideoCaptureParameter', grabber, 'Iris');
     rc.Focus = Screen('SetVideoCaptureParameter', grabber, 'Focus');
     rc.Zoom = Screen('SetVideoCaptureParameter', grabber, 'Zoom');
     rc.Pan = Screen('SetVideoCaptureParameter', grabber, 'Pan');
     rc.Tilt = Screen('SetVideoCaptureParameter', grabber, 'Tilt');
     rc.OpticalFilter = Screen('SetVideoCaptureParameter', grabber, 'OpticalFilter');
     rc.CaptureSize = Screen('SetVideoCaptureParameter', grabber, 'CaptureSize');
     rc.CaptureQuality = Screen('SetVideoCaptureParameter', grabber, 'CaptureQuality');
     rc.FrameRate = Screen('SetVideoCaptureParameter', grabber, 'FrameRate');
     rc.TriggerDelay = Screen('SetVideoCaptureParameter', grabber, 'TriggerDelay');
     rc.Temperature = Screen('SetVideoCaptureParameter', grabber, 'Temperature');
     return;
end

if strcmp(cmd, 'SetAllSettings')
     % Set all known settings from passed struct:
     if nargin < 3
        error('You need to supply a conformant camera settings struct to SetAllSettings!');
     end

     % Retrieve new settings from rc.
     rc = varargin{1};

     % Set new settings from rc, assign old settings to returned struct rc:
     rc.brightness = Screen('SetVideoCaptureParameter', grabber, 'Brightness', rc.brightness);
     rc.gain = Screen('SetVideoCaptureParameter', grabber, 'Gain', rc.gain);
     rc.shutter = Screen('SetVideoCaptureParameter', grabber, 'Shutter', rc.shutter);
     rc.exposure = Screen('SetVideoCaptureParameter', grabber, 'Exposure', rc.exposure);
     rc.sharpness = Screen('SetVideoCaptureParameter', grabber, 'Sharpness', rc.sharpness);
     [rc.whitebalance1, rc.whitebalance2] = Screen('SetVideoCaptureParameter', grabber, 'WhiteBalance', rc.whitebalance1, rc.whitebalance2);
     [rc.whiteshadingR, rc.whiteshadingG, rc.whiteshadingB] = Screen('SetVideoCaptureParameter', grabber, 'WhiteShading', rc.whiteshadingR, rc.whiteshadingG, rc.whiteshadingB);
     rc.saturation = Screen('SetVideoCaptureParameter', grabber, 'Saturation', rc.saturation);
     rc.gamma = Screen('SetVideoCaptureParameter', grabber, 'Gamma', rc.gamma);
     rc.vendor = Screen('SetVideoCaptureParameter', grabber, 'GetVendorname');
     rc.model = Screen('SetVideoCaptureParameter', grabber, 'GetModelname');
     rc.hue = Screen('SetVideoCaptureParameter', grabber, 'Hue', rc.hue);
     rc.iris = Screen('SetVideoCaptureParameter', grabber, 'Iris', rc.iris);
     rc.Focus = Screen('SetVideoCaptureParameter', grabber, 'Focus', rc.Focus);
     rc.Zoom = Screen('SetVideoCaptureParameter', grabber, 'Zoom', rc.Zoom);
     rc.Pan = Screen('SetVideoCaptureParameter', grabber, 'Pan', rc.Pan);
     rc.Tilt = Screen('SetVideoCaptureParameter', grabber, 'Tilt', rc.Tilt);
     rc.OpticalFilter = Screen('SetVideoCaptureParameter', grabber, 'OpticalFilter', rc.OpticalFilter);
     rc.CaptureSize = Screen('SetVideoCaptureParameter', grabber, 'CaptureSize', rc.CaptureSize);
     rc.CaptureQuality = Screen('SetVideoCaptureParameter', grabber, 'CaptureQuality', rc.CaptureQuality);
     rc.FrameRate = Screen('SetVideoCaptureParameter', grabber, 'FrameRate', rc.FrameRate);
     rc.TriggerDelay = Screen('SetVideoCaptureParameter', grabber, 'TriggerDelay', rc.TriggerDelay);
     rc.Temperature = Screen('SetVideoCaptureParameter', grabber, 'Temperature', rc.Temperature);
     return;
end

if strcmp(cmd, 'BacklightCompensation')
     % This is only meaningful on the Unibrain Fire-i:
     % It maps to the 'Shutter' parameter...
     if IsFirei
        if nargin > 2
           rc = Screen('SetVideoCaptureParameter', grabber, 'Shutter', varargin{1});
        else
           rc = Screen('SetVideoCaptureParameter', grabber, 'Shutter');
        end
     else
        % Ignore it.
        rc = Inf;
     end

     return;
end

if ~isempty(strfind(cmd, 'ExposureTime'))
     if nargin > 2
        inval = varargin{1};
     else
        inval = [];
     end

     if IsA602f || IsFirei || IsA312fc
        % Call cam specific routine.
        if IsA602f
           rc = DoA602fCamExposureTime(grabber, inval);
        end
        
        if IsA312fc
           rc = DoA312fcCamExposureTime(grabber, inval);
        end

        if IsFirei
           rc = DoFireICamExposureTime(grabber, inval);
        end

        return;
     else
        % Unknown camera. We just fall-through, mapping exposure time to
        % Exposure setting.
        cmd = 'Exposure';
     end
end

if (IsA602f || IsA312fc || IsFirei) && (~isempty(strfind(cmd, 'Exposure')) || ~isempty(strfind(cmd, 'Shutter')))
     % These settings are ignored on the Unibrain Fire-i and Basler A 602f and A312fc.
     % They either control ExposureTime - for which we have a nice function -
     % or they control special settings...     
     rc = Inf;
     return;
end

% None above matched. We just assume we've got one of the
% generic parameter names and pass it to the Screen - function.
% This will handle the Set- , Get-, and Auto- case.
if nargin > 2
   rc = Screen('SetVideoCaptureParameter', grabber, cmd, varargin{1});
else
   rc = Screen('SetVideoCaptureParameter', grabber, cmd);
end

return;

% This routine maps exposure times in secs to register values and vice versa.
% It works for cameras from the Basler A60xf series. Formulas based on their
% online specs.
function rc = DoA602fCamExposureTime(grabber, inval)
   if isempty(inval)
      % Retrieve and map current setting. The A602f stores the value in Shutter.
      rawval = Screen('SetVideoCaptureParameter', grabber, 'Shutter');
      % Exposure time in seconds is just shuttervalue * timebase (fixed at 20 microseconds.)
      rc = rawval * 0.000020;
   else
      % Map and set new setting. Maximum exposuretime is also limited by 1/fps with fps = capture
      % framerate.
      rawval = min(inval/1000.0, (1.0/Screen('SetVideoCaptureParameter', grabber, 'GetFramerate'))-0.0005);
      rawval = round(rawval / 0.000020);
      % Clamp to valid range of cam: 20 microseconds to 33.3 milliseconds.
      rawval = min(rawval, 1665);
      rawval = max(rawval, 1);
      % Write new settings, return old settings:
      rawval = Screen('SetVideoCaptureParameter', grabber, 'Shutter', rawval);
      % Exposure time in seconds is just shuttervalue * timebase (fixed at 20 microseconds.)
      rc = rawval * 0.000020;
   end
 
   % Convert return value from seconds to milliseconds.
   rc = rc * 1000;
return;

% This routine maps exposure times in secs to register values and vice versa.
% It works for cameras from the Basler A312fc series. Formulas based on their
% online specs.
function rc = DoA312fcCamExposureTime(grabber, inval)
   if isempty(inval)
      % Retrieve and map current setting. The A312fc stores the value in Shutter.
      rawval = Screen('SetVideoCaptureParameter', grabber, 'Shutter');
      % Exposure time in seconds is just shuttervalue * timebase (fixed at 20 microseconds.)
      rc = rawval * 0.000020;
   else
      % Map and set new setting. Maximum exposuretime is also limited by 1/fps with fps = capture
      % framerate - 94.9 usecs, for a given target framerate:
      rawval = min(inval / 1000.0, (1.0 / Screen('SetVideoCaptureParameter', grabber, 'GetFramerate')) - 0.0000949);
      rawval = round(rawval / 0.000020);
      
      % Clamp to valid range of cam: 20 microseconds to 81.9 milliseconds.
      rawval = min(rawval, 4095);
      rawval = max(rawval, 1);
      
      % Write new settings, return old settings:
      rawval = Screen('SetVideoCaptureParameter', grabber, 'Shutter', rawval);
      
      % Exposure time in seconds is just shuttervalue * timebase (fixed at 20 microseconds.)
      rc = rawval * 0.000020;
   end

   % Convert return value from seconds to milliseconds.
   rc = rc * 1000;
return;

% This routine maps exposure times in secs to register values and vice versa.
% It works for cameras from the Unibrain Fire-i and Fire-400 series. Formulas based on their
% online lookup sheet:
function rc = DoFireICamExposureTime(grabber, inval)
   if ~isempty(inval)
      % Map and set new setting. Maximum exposuretime is also limited by 1/fps with fps = capture
      % framerate.
      expval = min(inval/1000.0, (1.0/Screen('SetVideoCaptureParameter', grabber, 'GetFramerate'))-0.0005);
      rawval = 0;

      % Mapping of exposure times to rawvalues is done via this hard-coded lookup table:
      if expval >= 0
         rawval = round(expval / 0.000016);
      end

      if expval > (128 * 0.000016)
         rawval = expval - (128 * 0.000016);
         rawval = 128 + round(rawval / 0.000032);
      end

      if expval > (128 * 0.000016 + (192-128) * 0.000032)
         rawval = expval - (128 * 0.000016 + (192-128) * 0.000032);
         rawval = 192 + round(rawval / 0.000064);
      end

      if expval > (128 * 0.000016 + (192-128) * 0.000032 + (384-192) * 0.000064)
         rawval = expval - (128 * 0.000016 + (192-128) * 0.000032 + (384-192) * 0.000064);
         rawval = 384 + round(rawval / 0.000128);
      end

      % Clamp to valid range of cam: 20 microseconds to 81.9 milliseconds.
      rawval = min(rawval, 511);
      rawval = max(rawval, 0);
      % Write new settings, return old settings:
      rawval = Screen('SetVideoCaptureParameter', grabber, 'Exposure', rawval);
   else
      % Retrieve current setting:
      rawval = Screen('SetVideoCaptureParameter', grabber, 'Exposure');
   end

   % Need to map returned rawval into meaningful value:
   if rawval >= 0 && rawval <= 128
      rc = rawval * 0.000016; % Stepping of 16 microsecs.
   end
   
   if rawval > 128 && rawval <= 192
      rc = 128 * 0.000016 + (rawval-128) * 0.000032; % Stepping of 32 microsecs.
   end

   if rawval > 192 && rawval <= 384
      rc = 128 * 0.000016 + (192-128) * 0.000032 + (rawval-192) * 0.000064; % Stepping of 64 microsecs.
   end

   if rawval > 384
      rc = 128 * 0.000016 + (192-128) * 0.000032 + (384-192) * 0.000064 + (rawval-384) * 0.000128; % Stepping of 128 microsecs.
   end

   % Convert rc from seconds to milliseconds.
   rc = rc * 1000.0;
return;