kbcheck problem with waitVBL & usb buttonbox

Hi,
I'm having a problem with retrieving keypresses when we use a USB button
box connected to a mac and poll for key presses using kbcheck.m during a
movie loop that uses SCREEN('WaitVBL'). (see sample code below)

Key presses are recorded just fine if any of the three conditions are
met:
1) we use the computer keyboard rather than the usb button box
2) WaitVBL is removed
3) button box key presses are registered using getChar or a simpletext
window

Any idea why keypresses are lost using the combination of KBCHECK,
waitVBL, and a custom USB response box?
Is there any easy way to get around this problem?

Thanks in advance,
Frank
--
Frank Tong
Assistant Professor
Green Hall
Department of Psychology
Princeton University
Princeton, NJ 08544

tel: 609-258-2652
fax: 609-258-1113
web: http://www.princeton.edu/~ftong/



Sample excerpt of movie loop
for theFrame = 1:nFrames
SCREEN('CopyWindow',mpimagelist(mpmovielist(theFrame,num)) ...
,wptr,srcRect,dstRect,'srcCopy');

[keyIsDown,secs,keyCode] = KbCheck; % during keypress keyIsDown=1,
else keyIsDown=0
if(keyIsDown & ~lastKeyIsDown)
keyList(idx) = find(keyCode); % store current keycode in
keyList(idx)
rtList(idx) = (theRep-1)*nFrames+theFrame; % store current frame
in rtList(idx)
idx = idx+1; % increase idx by 1 to record next response
end
lastKeyIsDown = keyIsDown; % store whether key was just down or
not

SCREEN(wptr,'WaitVBL',waitFrames);
end
Hi Denis,
Thanks very much for your suggestions.
I tried using the updated screen command, WaitBlanking, and also played with
various screen preferences, including WaitBlankingAlwaysCallsSetClut, but
the custom button box continued to miss many keypresses.

Attached is the program we used to diagnose the problem and appended below
are the ScreenTest results (though we get the same loss of keypresses on a
variety of macs).

In testing the custom button box, we also found that:
- The custom USB button box registers that the KeyIsDown on only 1 frame
within movie loop containing kbcheck, and that this event is sometimes
missed by kbcheck with WaitBlanking in the movie loop. I'm not sure why.
(Perhaps the assigned interrupt priority of the custon button box keypress
is 0 rather than 1 and can't interrupt the WaitBlanking period? Could this
be an issue? If so, how can one check the priority level of a device? )

- In contrast, the USB mac keyboard registers that the KeyIsDown over many
frames (3-6 frames, varies in number from trial to trial) and perhaps
because of this, kbcheck always successfully registers the keypress.

Do you think the difference in the output signals from the keyboard vs.
custom button box may be responsible for the failure of kbcheck with the
button box?

As an alternative, using if(charAvail); getChar; end, in the movie loop I
can collect all the keypresses and don't seem to be losing frames. How
accurate is the timing on getChar on current macs?
Also, if I do start losing some frames, how accurate and fast is
PeekBlanking as a strategy to jump ahead in the movie if the movie loop runs
slower than wanted? Is this a good strategy?

Best regards,
Frank


****** CSBMB's PowerMac G3 Series/400, Mac OS 9.2.2 ******
G3, 400 MHz, memory bus 100 MHz, 48.167 Mflop/s
PsychToolbox 2.44, 7 August 2000, MATLAB 5.2.1.1421
QuickTime 5.0.2
No screen saver.
Using UpTime-based timing, which is very accurate and reliable.
Has serial port arbitration.
*** Screen 0 *************************************************************
ATY,Rage128y (.Display_Rage128 version 1.0f47) in slot J12
8 bit dacs. 1024x768 75 Hz. (56,60,67,70,72,75 Hz avail)
Yay! SCREEN Preference AskSetClutDriverToWaitForBlanking set 0 failed (get
0,actual 1), set 1 ok.
NOTE: DipPriorityAfterSetClut is true. Works around Rage128 driver bug.
NOTE: MinimumSetClutPriority is 2. Works around Rage128 driver bug.
pixel size 8 16 32 bits
pages 1 1 1
CopyWindow (ie CopyBits) 65 65 64 MB/s
GetClut equals SetClut? == == ==
SetClutDriverWaitsForBlanking? Yes
At priority 7 ... No blanking intrpts.
SetClut (cscSetEntries) min dur. 0.0 0.0 0.0 frames
At priority 1 ... Blanking interrupts.
SetClut (cscSetEntries) min dur. 0.5 0.0 0.5 frames
SetClut suppresses ints. for 0.0 0.0 0.0 frames
**************************************************************************


Denis Pelli wrote:

> >Hi,
> >I'm having a problem with retrieving keypresses when we use a USB button
> >box connected to a mac and poll for key presses using kbcheck.m during a
> >movie loop that uses SCREEN('WaitVBL'). (see sample code below)
> >
> >Key presses are recorded just fine if any of the three conditions are
> >met:
> >1) we use the computer keyboard rather than the usb button box
> >2) WaitVBL is removed
> >3) button box key presses are registered using getChar or a simpletext
> >window
> >
> >Any idea why keypresses are lost using the combination of KBCHECK,
> >waitVBL, and a custom USB response box?
> >Is there any easy way to get around this problem?
> >
> >Thanks in advance,
> >Frank
> >--
> >Frank Tong
> >Assistant Professor
> >Green Hall
> >Department of Psychology
> >Princeton University
> >Princeton, NJ 08544
> >
> >tel: 609-258-2652
> >fax: 609-258-1113
> >web: http://www.princeton.edu/~ftong/
> >
> >
> >
> >Sample excerpt of movie loop
> > for theFrame = 1:nFrames
> > SCREEN('CopyWindow',mpimagelist(mpmovielist(theFrame,num)) ...
> > ,wptr,srcRect,dstRect,'srcCopy');
> >
> > [keyIsDown,secs,keyCode] = KbCheck; % during keypress keyIsDown=1,
> >else keyIsDown=0
> > if(keyIsDown & ~lastKeyIsDown)
> > keyList(idx) = find(keyCode); % store current keycode in
> >keyList(idx)
> > rtList(idx) = (theRep-1)*nFrames+theFrame; % store current frame
> >in rtList(idx)
> > idx = idx+1; % increase idx by 1 to record next response
> > end
> > lastKeyIsDown = keyIsDown; % store whether key was just down or
> >not
> >
> > SCREEN(wptr,'WaitVBL',waitFrames);
> > end
> >
>
> dear frank
>
> i don't have any direct experience of using custom USB devices, but
> perhaps i can still help.
>
> is your "computer keyboard" also USB?
>
> you say "WaitVBL", but the recommended name has been "WaitBlanking"
> for several years. The old obsolete usage is still functional and
> equivalent, but i makes me wonder whether you're using the current
> release of the software. it would help to see a report from
> ScreenTest.
>
> when you call SCREEN 'WaitBlanking' (if you'll allow me to use the
> preferred name), there are several ways for SCREEN to implement the
> wait. the main issue is whether it uses the blanking interrupt or the
> side-effect of SetClut, that it waits for blanking. SCREEN sets this
> up automatically when you open your first window on that screen, but
> you can override its choice through use of SCREEN Preference.
>
> I don't see any reason why your problem should exist, since i'd
> expect the USB task to be interrupt driven and there's nothing in
> your code that i'd expect to block interrupts. however, if
> WaitBlanking uses SetClut, which is implemented by a call to the
> graphics driver, it is possible that the driver is badly written and
> in fact blocks interrupts while it's waiting for blanking.
> (ScreenTest specifically tests for this, and reports the result.)
>
> thus it might be instructive and fruitful to play with the Preference
> settings to try both methods of WaitBlanking. try turning
> WaitBlankingAlwaysCallsSetClut on and try turning it off. do this
> AFTER opening your first window on that screen.
>
> a program fragment is instructive, but it's better if you can supply
> a minimal program that exhibits the fault. something that others can
> actually run.
>
> best
>
> denis

--
Frank Tong
Assistant Professor
Green Hall
Department of Psychology
Princeton University
Princeton, NJ 08544

tel: 609-258-2652
fax: 609-258-1113
web: http://www.princeton.edu/~ftong/
>Hi Denis,
>Thanks very much for your suggestions.
>I tried using the updated screen command, WaitBlanking, and also played with
>various screen preferences, including WaitBlankingAlwaysCallsSetClut, but
>the custom button box continued to miss many keypresses.
>
>Attached is the program we used to diagnose the problem and appended below
>are the ScreenTest results (though we get the same loss of keypresses on a
>variety of macs).
>
>In testing the custom button box, we also found that:
>- The custom USB button box registers that the KeyIsDown on only 1 frame
>within movie loop containing kbcheck, and that this event is sometimes
>missed by kbcheck with WaitBlanking in the movie loop. I'm not sure why.
>(Perhaps the assigned interrupt priority of the custon button box keypress
>is 0 rather than 1 and can't interrupt the WaitBlanking period? Could this
>be an issue? If so, how can one check the priority level of a device? )
>
>- In contrast, the USB mac keyboard registers that the KeyIsDown over many
>frames (3-6 frames, varies in number from trial to trial) and perhaps
>because of this, kbcheck always successfully registers the keypress.
>
>Do you think the difference in the output signals from the keyboard vs.
>custom button box may be responsible for the failure of kbcheck with the
>button box?
>
>As an alternative, using if(charAvail); getChar; end, in the movie loop I
>can collect all the keypresses and don't seem to be losing frames. How
>accurate is the timing on getChar on current macs?
>Also, if I do start losing some frames, how accurate and fast is
>PeekBlanking as a strategy to jump ahead in the movie if the movie loop runs
>slower than wanted? Is this a good strategy?
>
>Best regards,
>Frank

>flag1 = 1;
>while flag1
> [keyIsDown, timeSecs, arrkey1] = KbCheck; % Check for a key press
> if keyIsDown
> ...
> end
> SCREEN(window,'WaitBlanking'); % Works fine with this line omitted, but
> % misses button box input with this line
included
>end

dear frank

thanks for including the program. it cleared up some things for me.

...
>the custom button box continued to miss many keypresses.
...
>In testing the custom button box, we also found that:
>- The custom USB button box registers that the KeyIsDown on only 1 frame
>within movie loop containing kbcheck, and that this event is sometimes
>missed by kbcheck with WaitBlanking in the movie loop.
>- In contrast, the USB mac keyboard registers that the KeyIsDown over many
>frames (3-6 frames, varies in number from trial to trial) and perhaps
>because of this, kbcheck always successfully registers the keypress.
>Do you think the difference in the output signals from the keyboard vs.
>custom button box may be responsible for the failure of kbcheck with the
>button box?

KbCheck will only see the key press if it samples while the keypress
signal is asserted. From your testing, it is clear that the Apple
keyboard asserts the keypress signal for a good long time (at least 3/75
s = 40 ms), while your custom button box is asserting the signal only
very briefly (less than 10 ms). My earlier comments about interrupts and
interrupt priority are not relevant. Once possible fix would be to ask
the button box designer to increase the duration of the keypress
assertion to be longer, more like Apple's keyboard.

>As an alternative, using if(charAvail); getChar; end, in the movie loop I
>can collect all the keypresses and don't seem to be losing frames. How
>accurate is the timing on getChar on current macs?

We've just enhanced GetChar to return the Mac OS time stamp of the
keypress. It's measured in 60.15 Hz ticks, so it's about 1 frame. I would
guess that this is adequate for most purposes.

The new GetChar is enclosed in a recent forum message.

>Also, if I do start losing some frames, how accurate and fast is
>PeekBlanking as a strategy to jump ahead in the movie if the movie loop runs
>slower than wanted? Is this a good strategy?

PeekBlanking is very accurate. Yes, you could use it to jump ahead.
However, if, in the end, the trial is messed up you should discard its
data. I suspect that you can get things under control and not miss
frames. PeekBlanking is an excellent way of confirming that you haven't
missed a frame.

we'd welcome comments on how well GetChar does in measuring reaction time.

best

denis