function  record = do_PLE2_trial(P,orient,diff,NC_idx,pos)

%DO_PLE2_TRIAL -- Project a stimulus and get response from the subject.
%
%  record = do_PLE2_trial(P,orient,diff,NC_idx,pos)
%
%  DO_PLE2_TRIAL performs a single trial of the Perceptual Learning Exp2.
%  It assumes all screens and sound channels are already open.
%
%  P is a "master parameter structure" specifying the Gabor patches,
%  movieStructs, sounds, and other parameters (see PLEXP2_PARAMS).
%  In addition to the parameters used by MAKE_PLE2_STIM ('Gabor','colors',
%  'LUT_params','mask_idx'), DO_PLE2_TRIAL uses the following fields: 
%  'movieStruct','fix_buffPtr','blank','times','sounds','Gabor_argmax'.
%  ORIENT, DIFF, and NC_idx are passed to MAKE_PLE2_STIM.
%  POS is an index in P.position and P.movieStruct specifying the
%  position at which the stimulus will appear on the screen.
%
%  RECORD is a row vector of the following ten numbers:
%   1. time stamp -- GetSecs just before the main stimulus presentation
%   2. stimulus orientation -- a copy of ORIENT
%   3. difficulty level -- a copy of DIFF
%   4. NOISE_CACHE index -- a copy of NC_idx
%   5. presentation position -- a copy of POS
%   6. sanity-check value -- luminance of stimulus pixel #Gabor_argmax
%   ----------- 
%   7. response key pressed by the subject (see P.keys and GET_RESPONSE)
%   8. correct -- 1 iff RESPONSE==ORIENT   for phase 1 (see PLExp2),
%                 1 iff RESPONSE==5-ORIENT for phase 2 (see PLExp2a),
%                 if (Gabor_orient<0), 1 iff (resp==3+Gabor_orient), ph.3
%   9. response time -- from the stimulus onset until the keypress, msec
%  10. exit code -- 0 for successful trials, 1 for invalid keys, 2 for
%           invalid presentation duration (due to missed video frames)
%  11. play time -- as returned by PLAYMOVIESTRUCT, in seconds.
%  Note that this format is different from the one in DO_PLE_TRIAL.
%
%  See also PLEXP2, PLEXP2A, PLEXP2B, MAKE_PLE2_STIM, DO_PLE_TRIAL.

%  Original coding by Alexander Petrov, UC Irvine.
%  $Revision: 1.2 $  $Date: 2003/09/08 11:27 $

%-- Generate an appropriate stimulus
flip = sign(orient) ;             % for phase 3: +1=dont_flip, -1=flip
stim = make_PLE2_stim(P,abs(orient),diff,NC_idx) ;
if (flip==-1)  stim = flipLR(stim) ;  end      % <-- phase 3
sanity_check = stim(P.Gabor_argmax) ;

%-- Load it into the appropriate offscreen buffer
mvStruct = P.movieStruct(pos) ;
winPtr = mvStruct.windowPtr ;
LoadMovieStruct({stim,P.blank},mvStruct) ;

%-- Get ready for the stimulus presentation
SCREEN(winPtr,'WindowToFront') ;         % in case of stray clicks, etc.
SCREEN(winPtr,'PutImage',P.fixation) ;   % crosshair
WaitSecs(P.times.fix2alert) ;
SND('Play',P.sounds.alert) ;
WaitSecs(P.times.alert_onset) ;

%-- Present the main stimulus for a strictly controlled amount of time
[startTime,finishTime] = PlayMovieStruct(mvStruct) ;   % <-- sic!

%-- Wait for response from the subject, without auditory feedback
[resp,keySecs] = get_response(P.keys) ;                % <-- sic!
if (orient<0)        % flipped vertical orientations, phase 3
   correct = (resp==3+orient) ;     % 3+(-1)=2=R ; 3+(-2)=1=L
elseif (orient<=2)   % vertical orientations, phases 1 and 3
   correct = (resp==orient) ;
else  % ORIENT must be either 3 or 4 -- horizontal orients, phase 2
   correct = (resp==(5-orient)) ;       % "1" for 4 and "2" for 3
end
% Note that no auditory feedback is given

%-- Get rid of the fixation crosshair (and any other leftovers)
SCREEN(winPtr,'FillRect',P.colors.gray) ;

%-- Verify that the stimulus duration really was as it should
play_time = finishTime - startTime ;
target_play = P.times.target_play ;
if (abs(play_time-target_play)/target_play > 0.005)  % 0.5% tolerance
   exitcode = 2 ;    % missed video frame
elseif (resp<1)
   exitcode = 1 ;    % illegal key
   SND('Play',P.sounds.badkey) ;
else
   exitcode = 0 ;    % OK
end

%-- Pack results and return RECORD
record = zeros(1,10) ;
record(1) = startTime ;     % absolute time stamp of stimulus onset, sec
record(2) = orient ;
record(3) = diff ;
record(4) = NC_idx ;
record(5) = pos ;
record(6) = sanity_check ;
record(7) = resp ;
record(8) = correct ;
record(9) = (keySecs-startTime) * 1000 ;     % response time, msec
record(10)= exitcode ;
record(11)= play_time ;

%%%  Return RECORD
%%%%% End of the main function

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function  [resp,keySecs] = get_response(keys,flushp) ;

%GET_RESPONSE -- Get timed response from the keyboard.
%
%  [resp,keySecs] = get_response(keys,[flushp])
%
%  KEYS is a cell array of strings, interpreted as character sets.
%  RESP is the index of the first set that contains the key pressed by
%  the subject. If the subject presses an invalid key, RESP=0.
%  KEYSECS is the time stamp of the key press (as returned by KBCheck).
%
%  Warning: This routine does not work if MATLAB's "backgrounding" is
%           enabled. Type 'helpwin CharAvail' for details.
%
%  Example:
%    yesKeys = 'sdfSDF' ; noKeys = 'jklJKL' ;
%    startSecs = GetSecs;
%    PresentStumulus(...) ;
%    [resp,keySecs] = get_response({noKeys,yesKeys}) ;
%    RT = keySecs-startSecs ;
%    
%  See also KBCHECK, GETCHAR, GETSECS, ISMEMBER.

%  Original coding by Alexander Petrov, UC Irvine.
%  $Revision: 1.0 $  $Date: 2001/12/13 21:24 $

if (nargin < 2)  flushp = 1 ; end
if (flushp)
   FlushEvents('keyDown') ;
end

while (1)
   [keyIsDown,keySecs] = KbCheck ;    % get the timing, fast
   if CharAvail
      c = GetChar ;                   % translate the char, slow
      break
   end
end

resp = 0 ;
for k = 1:length(keys)
   if (ismember(c,keys{k}))
      resp = k ;
      break
   end
end

%--- Return RESP and KEYSECS  
%%% End of subfunction GET_RESPONSE

%%%%% End of file DO_PLE2_TRIAL.M
