function KbDemo
% KbDemo illustrates the use of KbCheck and KbWait, which provide 
% fast monitoring of the keyboard state, and KbName, which converts a keyCode to a keyName.
% 
% 1. Report keyboard key number for any pressed key(s). This includes
% modifier keys such as <shift>, <control>, <caps lock> and <option>. The
% only key not reported is the start key, which turns on your computer.
% 
% 2. Report time of keypress, using KbCheck.
% 
% 3. Report time of keypress, using KbWait.
% 
% 4. Use keys as real-time controls of a dynamic display.
% 
% Works fine the with Keyspan Digital Media Remote:
% web http://www.keyspan.com/products/usb/remote/
% However, the Digital Media Remote is a bit sluggish (max alternating key rate of 2 Hz),  
% suggesting that it may not be well suited for measuring reaction time.

% See KbName, KbCheck, and KbWait.
%
% David Brainard, January, 1997
% Allen Ingling, February, 1998

% 1/22/97	dhb	Wrote demos 2 & 3, as KeyTimingDemo.
% 3/6/97	dhb	Change from TIMER to modern routines.
% 3/8/97	dgp	Polished the instructions.
% 8/2/97	dgp	Call FlushEvents('keyDown') after getting each
% 				key press, to start fresh each time.
% 				Explain difference between key presses and characters.
% 1/28/98	dgp	Explain effect of CapsLock key.
% 2/28/98	dgp	Mention new capability of KbCheck.
% 2/18/98	awi	Wrote demos 1 & 4.
% 2/19/98	dgp	Folded in awi's KbExplore.
% 2/28/98	dgp	Folded in dhb's KeyTimingDemo.
% 3/2/98	dgp	Cosmetic.
% 3/9/98	dhb Change case of screen to Screen.
%				Force 8-bit depth. DefaultClut.
% 3/10/98	dgp	Allow all depths. Use new WhiteIndex and BlackIndex.
% 3/12/98	dgp	Make sure Backgrounding is off.
% 3/19/99	dgp	Use KbName. We no longer use GetChar, so Backgrounding no longer matters.
% 6/6/00	dgp	Use arrow and escape keys instead of a, s, and q to allow use with
%				the Keyspan Digital Media Remote, which has no letter keys.
%				http://www.keyspan.com/products/usb/remote/
% 2/11/01   awi Added platform conditionals for font names.
%               Conditionally call flushevents only on Mac. 
% 4/3/02    awi Restored flushevents under Windows
% 4/13/02   dgp Use Arial, eliminate conditionals.

% 1. Display keyNumbers of pressed keys.
fprintf('1 of 4. Testing KbCheck and KbName: Press any key(s). Press the escape key to proceed to the next demo.\n');
while KbCheck;end; % wait until all keys are released.
escapeKey = KbName('esc');
shiftKey=KbName('shift');
capsLockKey=KbName('capslock');
while 1
	touch = 0;
	while ~touch
		[touch, secs, keyCode] = KbCheck;
	end
	t=GetSecs;
	FlushEvents('keyDown');	% discard all the chars from the Event Manager queue.
    fprintf(['You pressed key(s) ' int2str(find(keyCode)) ' which is %s\n'],KbName(keyCode));
	if keyCode(escapeKey)
		break;
	end
	while keyCode(shiftKey) | keyCode(capsLockKey)
		if GetSecs>t+2
			fprintf('The shift key still seems to be down. Did you press Caps Lock?\n');
			break;
		end
		[touch, secs, keyCode] = KbCheck;
	end
	while KbCheck;end; % wait until key is released.
end

% 2. Run a loop on KbCheck. If a key is pressed, CharAvail and GetChar are used
% to pick up the character generated. 
fprintf('\n2 of 4. Testing KbCheck timing: Please hit a few keys. (Try shift keys too.)\n');
fprintf('(If you hit CapsLock, I''ll think you''re holding the shift key down,\n');
fprintf('and won''t proceed until you undo the shift by hitting CapsLock again.)\n');
fprintf('Hit the escape key to proceed to the next demo.\n');
WaitSecs(0.5);
startSecs = GetSecs;
while 1
	[keyIsDown,timeSecs,keyCode] = KbCheck;
	if keyIsDown
		char = KbName(keyCode);
		% The initial 1 in the fprintf is needed. Otherwise '5%' won't print.
		fprintf(1,'"%s" hit at time %.3f s\n',char,timeSecs-startSecs);
		if keyCode(escapeKey)
			break;
		end
		while KbCheck; end
	end
end
FlushEvents('keyDown');	% discard all the chars from the Event Manager queue.


% 3. Wait for a key with KbWait.
WaitSecs(0.5);
fprintf('\n3 of 4. Testing KbWait: hit any key. Just once.\n');
startSecs = GetSecs;
timeSecs = KbWait;
[keyIsDown,t,keyCode] = KbCheck;
% The initial 1 in the fprintf is needed. Otherwise '5%' won't print.
fprintf(1,'"%s" hit at time %.3f s\n',KbName(keyCode),timeSecs-startSecs);
FlushEvents('keyDown');	% discard all the chars from the Event Manager queue.


% 4. Use keypresses as dynamic game controls.
% Open an onscreen window
white=WhiteIndex(0);
[w,wRect]=Screen(0,'OpenWindow',white);
%[w,wRect]= Screen(0,'OpenWindow',0,[],8);
%Screen(w,'SetClut',ClutDefault(w));
srcRect=[0,0,100,100];
dstRect=CenterRect(srcRect,wRect);

% Make a movie in offscreen windows
white=WhiteIndex(w);
black=BlackIndex(w);
dotRect0=CenterRect([0 0 12 12],srcRect);
radius=dotRect0(RectLeft);
angle=linspace(0,2*pi,100);
mov=zeros(size(angle));
for i=1:length(mov)
	mov(i)=Screen(w,'OpenOffscreenWindow',white,dstRect);
	dotRect=OffsetRect(dotRect0,radius*sin(angle(i)),radius*cos(angle(i)));
	Screen(mov(i),'FillOval',black,dotRect);
end

% Draw instructions in window
Screen(w,'TextFont','Arial');
Screen(w,'TextSize',18);
black=BlackIndex(w);
Screen(w,'DrawText','4 of 4. Please press the left or right arrow key to move, or the escape key to quit.',20,20,black);

% Read the keyboard once per frame.  Play the movie either forward or 
% backward, depending on the key pressed.
rightKey = KbName('right');	% clockwise key
leftKey = KbName('left');	% anti-clockwise key
escapeKey = KbName('esc');	% quit key
cntr = 0; 
while 1
	Screen(w,'WaitBlanking')
	Screen('CopyWindow',mov(mod(cntr,length(mov))+1),w,srcRect,dstRect);
	[a,b,keyCode] = KbCheck;
	if keyCode(rightKey)
		cntr = cntr + 1;
	elseif keyCode(leftKey)
		cntr = cntr - 1;
	end
	if keyCode(escapeKey)
		break;
	end
end
FlushEvents('keyDown');	% discard all the chars from the Event Manager queue.


% close the windows
Screen('CloseAll');
fprintf('\n4 of 4. Done.\n');
