Created
January 8, 2015 22:26
-
-
Save dxjones/75640b579b003e42f30b to your computer and use it in GitHub Desktop.
Revisions
-
dxjones created this gist
Jan 8, 2015 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,235 @@ % Demo_FlipBug.m % % 2015-01-08 [email protected] % % set ShowBug to false to avoid missed Flips % set ShowBug to true to demonstrate missed Flips ShowBug = true; % see line #75 try Priority(9); w = Screen('OpenWindow', 0); FlipInterval = Screen('GetFlipInterval', w); winfo = Screen('GetWindowInfo', w); vblank = winfo.VBLStartline; vtotal = winfo.VBLEndline; % - - - - - r = Screen('Rect', 0); ScreenHeight = RectHeight(r); ScreenWidth = RectWidth(r); cx = ScreenWidth/2; cy = ScreenHeight/2; zx = cx - (vtotal/2); zy = cy - (vtotal-vblank)/2; radius = 0.45 * min(ScreenHeight, ScreenWidth); x0 = (ScreenWidth/2) - (vtotal/2); x1 = x0 + vtotal; x_vblank = x0 + (x1-x0) * (vblank/vtotal); y0 = 0.10 * ScreenHeight; y1 = y0 + 0.80 * ScreenHeight; y_vblank = y1 - (y1-y0) * (1/1.5); % - - - - - N = 1 + vtotal; beam = false(N,1); vt = zeros(N,1); m = zeros(N,1); bp = zeros(N,1); t_pre = zeros(N,1); t_post = zeros(N,1); t_mid = zeros(N,1); vt_pre = zeros(N,1); vt_post = zeros(N,1); vt_mid = zeros(N,1); % main loop includes random delays to get a variety of beam positions % "beamcount" controls how many different beam positions we need % Caution: main loop will become very slow if beamcount > 0.95 * vtotal beamcount = 0.95 * vtotal; VBL_timestamp = 0; while true if nnz(beam) >= beamcount break end if KbCheck break end % simple animation shows progress through loop y = nnz(beam); Screen('DrawLine', w, 0, 100,y, 400,y); % wait a random delay delay = rand * FlipInterval; WaitSecs(delay); if ShowBug WaitSecs(2*FlipInterval); end % wait for a beampos we haven't seen before while true t0 = GetSecs; beampos = Screen('GetWindowInfo', w, 1); t1 = GetSecs; b = 1 + beampos; if ~beam(b) beam(b) = true; break end break end % Flip when = 0; % when = GetSecs + 0.010; [VBL_timestamp Stim_timestamp Flip_timestamp Missed Beampos_after_Flip ] = Screen('Flip', w, when,1); % Calculate Flip Time % (normally, this would be done before the Flip) t_pre(b) = t0; t_post(b) = t1; t_mid(b) = (t0 + t1) / 2; vt_pre(b) = CalculateFlipTime(t_pre(b), beampos, vblank, vtotal, FlipInterval); vt_post(b) = CalculateFlipTime(t_post(b), beampos, vblank, vtotal, FlipInterval); vt_mid(b) = CalculateFlipTime(t_mid(b), beampos, vblank, vtotal, FlipInterval); FlipDelta = VBL_timestamp - vt_mid(b); % record actual VBL, etc. vt(b) = VBL_timestamp; m(b) = Missed; bp(b) = Beampos_after_Flip; % - - - - - px = x0 + (x1-x0) * (b/vtotal); py = y1 - (y1-y0) * ((Beampos_after_Flip - vblank) / (1.5*(vtotal - vblank))); Screen('DrawLine', w, 128, x0,y0, x0,y1); Screen('DrawLine', w, 128, x1,y0, x1,y1); Screen('DrawLine', w, 128, x0,y0, x1,y0); Screen('DrawLine', w, 128, x0,y1, x1,y1); Screen('DrawLine', w, 128, x_vblank,y0, x_vblank,y1); Screen('DrawLine', w, 128, x0,y_vblank, x1,y_vblank); if FlipDelta < (FlipInterval/2) color = [0 255 0 255]; else color = [255 0 0 255]; Screen('FillRect', w, color, [px-1 y1+10 px+1 y1+110]); end Screen('FillRect', w, color, [px-1 py-3 px+1 py+3]); % - - - - - end % hocus-pocus to make sure we close all windows wlist = Screen('Windows'); Screen('CloseAll'); Priority(0); catch e CatchGraphicsError(e, 'BeginGraphics'); % hocus-pocus to make sure we close all windows wlist = Screen('Windows'); Screen('CloseAll'); Priority(0); end scanline = 0:vtotal; scanlines_per_msec = (vtotal+1) / (1000 * FlipInterval); % guess at beampos deadline for successful flips vdeadline = 0.75 * vblank; %% % Figure 1 shows Beampos before/after Flip % % Notice Beampos after Flip is almost always ... % between vblank and vtotal, occasionally wraps around % % adjust returned beampos to wrap around past the end of vtotal X = bp < (vtotal/2); bp( X ) = bp( X ) + (1+vtotal); figure(1); plot(vtotal*[0 1],[0 0],'k:', ... vtotal*[0 1], vblank*[1 1],'k:',... vtotal*[0 1], vtotal*[1 1],'k:', ... [0 0], vtotal*[0 1],'k:', ... vdeadline*[1 1],vtotal*[0 1],'g:', ... vblank*[1 1], vtotal*[0 1], 'k:', ... vtotal*[1 1], vtotal*[0 1], 'k:', ... scanline(beam),bp(beam),'r.'); % vblank - scanlines_per_msec*[1 1], vtotal*[-1 2],'r:', ... % vblank - scanlines_per_msec*[2 2], vtotal*[-1 2],'r:', ... % vblank - scanlines_per_msec*[3 3], vtotal*[-1 2],'r:', ... % vblank - scanlines_per_msec*[4 4], vtotal*[-1 2],'r:', ... % vblank - scanlines_per_msec*[5 5], vtotal*[-1 2],'r:', ... % vblank - scanlines_per_msec*[6 6], vtotal*[-1 2],'r:', ... % vblank - scanlines_per_msec*[7 7], vtotal*[-1 2],'r:', ... xlabel('Beampos before Flip'); ylabel('Beampos after Flip'); text(vtotal/2, vblank, 'VBLANK'); text(vtotal/2, vtotal, 'VTOTAL'); axis([0 vtotal vblank-10 vtotal+10]); axis square %% % Figure 2 shows accuracy of Calculated Flip Time % % Notice blue data points are very close to zero delta_pre = vt - vt_pre; delta_post = vt - vt_post; delta_mid = vt - vt_mid; figure(2); plot(vtotal*[0 1],[0 0],'k:', ... vtotal*[0 1],1000*FlipInterval*[1 1],'k:', ... vtotal*[0 1],(vtotal+1)*[1 1],'k:', ... vdeadline*[1 1],1000*FlipInterval*[-1 2],'g:', ... vblank*[1 1],1000*FlipInterval*[-1 2],'k:', ... vtotal*[1 1],1000*FlipInterval*[-1 2],'k:', ... scanline(beam),1000*delta_pre(beam),'g.', ... scanline(beam),1000*delta_mid(beam),'b.', ... scanline(beam),1000*delta_post(beam),'r.'); figure(2), axis([0 vtotal -0.2 0.2]); xlabel('Beampos before Flip'); ylabel('Flip Time Prediction Error (msec)'); title('Flip Time Prediction Error ... +ve means actual Flip occured later'); %% % Figure 3 highlights missed Flips figure(3); plot(vtotal*[0 1],[0 0],'k:', ... vtotal*[0 1],1000*FlipInterval*[1 1],'k:', ... vtotal*[0 1],(vtotal+1)*[1 1],'k:', ... vdeadline*[1 1],1000*FlipInterval*[-1 2],'g:', ... vblank*[1 1],1000*FlipInterval*[-1 2],'k:', ... vtotal*[1 1],1000*FlipInterval*[-1 2],'k:', ... scanline(beam),1000*delta_pre(beam),'g.', ... scanline(beam),1000*delta_mid(beam),'b.', ... scanline(beam),1000*delta_post(beam),'r.'); figure(3), axis([0 vtotal 1000*FlipInterval-0.2 1000*FlipInterval+0.2]); xlabel('Beampos before Flip'); ylabel('Flip Time Prediction Error (msec)'); title('Flip Time Prediction Error ... (Missed Flips) ... +ve means actual Flip occured later');