function secs = KbTriggerWait(keyCode, deviceNumber) % secs = KbTriggerWait(keyCode, [deviceNumber]) % % Waits until one or more trigger keys have been pressed and returns the % time of the first key press in seconds. The keyCode argument can be a % vector of key indices. For example, to check for the 't' key as the % trigger use KbTriggerWait(KbName('t')), to check for 't' and the escape % key, use KbTriggerWait([KbName('t'), KbName('ESCAPE')]). % % You cannot use KbTriggerWait while a queue created by KbQueueCreate % exists. To shut down such a queue, use KbQueueRelease. % % On Matlab versions older than R2007a on MS-Windows, this function simply % serves as a convenient substitute for using KbCheck to detect the % trigger of interest. % % This function should allow triggers to be reliably detected from devices % that only briefly report that the key is down. KbCheck is not reliable % with such devices because it may not poll often enough to detect the % key down state. % % KbTriggerWait uses the PsychHID function, a general purpose function for % reading from the Human Interface Device (HID) class of USB devices. % Unlike KbCheck, it starts a queue that receives keyboard events % regarding the trigger key (and no other keys) and then polls this queue % (rather than the current key status) periodically. In theory, this % should also provide more accurate reporting of the time of the % triggering keypress. However, if multiple trigger events have occurred % since last polled, it is possible that the timestamp of the earliest % of these will have already rotated out of the limited capacity (eight % events) queue. In this case, the time of the earliest event remaining % in the queue is reported. Since the polling frequency is the same as % KbCheck, it should be more accurate on average with regard to timing, % even when the timestamps of the earliest events have been lost due to % queue overflow. % % KbTriggerWait tests the first USB-HID keyboard device by default. % Optionally, you can pass in a 'deviceNumber' to test a different keyboard % if multiple keyboards are connected to your machine. The function also % allows to wait for button presses on keypads, mice or other HID devices % with buttons or keys. % % Passing a deviceNumber of -1 will NOT cause all keyboards to be detected % % One disadvantage of this function is that it renders Matlab relatively % unresponsive to Ctrl-C interrupts. KbQueueWait is a better option in % this regard, but more complicated to use. % _________________________________________________________________________ % % See also: KbQueueWait KbCheck, KbWait, GetChar, CharAvail, KbDemo. % 8/10/07 rpw Wrote it. % 8/21/07 rpw Added comments about KbQueueWait as alternative % 8/23/07 rpw Added warning about incompatibility with KbQueueCreate, et al. % 5/14/12 mk Add new OSX path, MS-Windows pre R2007a path, other % tweaks. persistent macosxrecent; if isempty(macosxrecent) macosxrecent = IsOSX; LoadPsychHID; end % OSX? We no longer use PsychHID('KbTriggerWait'). Instead we emulate via % the KbQueueXXX interface. This has two advantages: % a) It works on 64-Bit OSX despite the incompatibilities and additional % brain-damage added to the low-level interface by our friendly iPhone % company. % b) It allows to wait for multiple keys, just as on Linux and Windows. % % Timestamp precision won't suffer, as past improvements to PsychHID's % KbQueue routines now query timestamps from the OS itself for high % precision. % if macosxrecent if nargin==2 % Nothing to do. elseif nargin == 1 deviceNumber = []; elseif nargin == 0 error('Trigger key code(s) must be specified in KbTriggerWait'); elseif nargin > 2 error('Too many arguments supplied to KbTriggerWait'); end % Emulate KbTriggerWait via KbQueueWait: keyCodes = zeros(1, 256); keyCodes(keyCode) = 1; KbQueueCreate(deviceNumber, keyCodes); secs = KbQueueWait(deviceNumber); KbQueueStop(deviceNumber); KbQueueRelease(deviceNumber); return; end if nargin < 2 deviceNumber = []; end % Try to reserve keyboard queue for 'deviceNumber' for our exclusive use: if ~KbQueueReserve(1, 2, deviceNumber) if isempty(deviceNumber) deviceNumber = NaN; end error('Keyboard queue for device %i already in use by GetChar() et al. Use of GetChar and keyboard queues is mutually exclusive!', deviceNumber); end if nargin==2 [secs]= PsychHID('KbTriggerWait', keyCode, deviceNumber); elseif nargin == 1 [secs]= PsychHID('KbTriggerWait', keyCode); elseif nargin == 0 error('Trigger key code must be specified in KbTriggerWait'); elseif nargin > 2 error('Too many arguments supplied to KbTriggerWait'); end % Try to release keyboard queue for 'deviceIndex' from our exclusive use: KbQueueReserve(2, 2, deviceNumber);