PageRenderTime 23ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/FlashStim.m

https://github.com/ko0sha/Flash-VEP-Stimulator
Objective C | 139 lines | 120 code | 19 blank | 0 comment | 17 complexity | 3a2b782ececfb48ca0cef014aa2f1e89 MD5 | raw file
  1. % FlashStim.m
  2. % Revisions:
  3. %
  4. % 1.2 updated variable name "flashCount" is more accurate
  5. % fixed problem related to Java "classpath.txt"
  6. % - PTB exception could occur during Key('create')
  7. % - solved by moving Graphics('create') before Key('create')
  8. % - added /Applications/Psychtoolbox/PsychJava to classpath.txt
  9. % added warning ...
  10. % - when stimulus frequency does not evenly divide display frequency
  11. % - requires Param('create') before Graphics('create')
  12. % fixed timing drift
  13. % - new program "FrameRate.m" measures actual CRT frame rate
  14. % - example: PTB reports 100 Hz, but measured rate is 100.559 Hz
  15. % - adjust FrameRate to match measured value
  16. % - adjust Stimulus Frequency, so it evenly divides FrameRate
  17. %
  18. % 1.1 fixed timing issue:
  19. % - detect FrameRate (note: PTB returns "0 Hz" for LCD)
  20. % - adjust to 60Hz nominal rate for LCD
  21. % - reduce "wait until time" by 1/2 frame time
  22. % - measure actual delay before 1st Flip to check for consistency
  23. % updated Graphics('create') so all fields in "G" are defined
  24. % - in case of PTB exception, ... Graphics('error'), Graphics('end')
  25. % added some comments in code
  26. %
  27. % 1.0 initial revision
  28. clear;
  29. fprintf('\nFlashStim 1.2\n');
  30. global P G K;
  31. Param('create');
  32. Graphics('create');
  33. Key('create');
  34. fprintf('\nParameters:\n');
  35. fprintf('\tFlash Frequency = %.3f Hz\n', P.Frequency);
  36. fprintf('\tDelay Before/After Stimulus = %d seconds\n', P.Delay);
  37. fprintf('\tStimulus Duration = %d seconds\n', P.Duration);
  38. fprintf('\nto begin, press SPACE ...\n');
  39. flashCount = 0;
  40. frameDelay = 0;
  41. frameMax = 0;
  42. preFlipDelay = 0;
  43. preFlipMax = 0;
  44. try
  45. Key('begin');
  46. escape = false;
  47. if Key('space') == -1
  48. fprintf('[ escape ]\n');
  49. escape = true;
  50. else
  51. fprintf('\nOK\n\n');
  52. WaitSecs(1);
  53. Graphics('begin');
  54. WaitSecs(P.Delay);
  55. if P.Debug
  56. Nframes = P.Duration * P.Frequency;
  57. timing = zeros(4, Nframes);
  58. end
  59. % synchronize with "frame refresh"
  60. Screen('FillRect', G.window, P.BlackLevel);
  61. start = Screen('Flip', G.window);
  62. stop = start + P.Duration;
  63. % wait 1/2 FramePeriod, so we always start loop in same state
  64. t = WaitSecs('UntilTime', start + 0.1*G.FramePeriod);
  65. while t < stop
  66. % should alway start loop 0.9 * FramePeriod before next Flip
  67. t0 = GetSecs;
  68. flashCount = flashCount + 1;
  69. % display White for 1 frame, then back to Black
  70. Screen('FillRect', G.window, P.WhiteLevel);
  71. t1 = Screen('Flip', G.window);
  72. Screen('FillRect', G.window, P.BlackLevel);
  73. t2 = Screen('Flip', G.window);
  74. % calculate delay before 1st Flip (to white)
  75. % - should be about 0.9 * FramePeriod
  76. delta = t1 - t0;
  77. if delta > preFlipMax, preFlipMax = delta; end
  78. preFlipDelay = preFlipDelay + delta;
  79. % calculate delay before 2nd Flip (to black)
  80. % - should be exactly 1 FramePeriod
  81. delta = t2 - t1;
  82. if delta > frameMax, frameMax = delta; end
  83. frameDelay = frameDelay + delta;
  84. if P.Debug
  85. timing(:,flashCount) = [ (start+(flashCount-1)*P.Period); t0; t1; t2 ] - start;
  86. end
  87. if Key('escape') == -1
  88. fprintf('[ escape ]\n');
  89. escape = true;
  90. break
  91. end
  92. % wait long enough to achieve desired temporal frequency
  93. t = WaitSecs('UntilTime', start + flashCount*P.Period + 0.1*G.FramePeriod);
  94. end
  95. if ~escape
  96. WaitSecs(P.Delay);
  97. end
  98. Graphics('end');
  99. end
  100. Key('end');
  101. catch e
  102. Graphics('error', e);
  103. end
  104. if flashCount > 0
  105. preFlipDelay = preFlipDelay / flashCount;
  106. frameDelay = frameDelay / flashCount;
  107. fprintf('Flash Count = %d\n', flashCount);
  108. fprintf('Pre-Flip Delay, Avg = %.3f msec, Max = %.3f msec, (expected = %.3f msec)\n', preFlipDelay*1000, preFlipMax*1000, 0.9*G.FramePeriod*1000);
  109. fprintf('Frame Delay, Avg = %.3f msec, Max = %.3f msec, (expected = %.3f msec)\n', frameDelay*1000, frameMax*1000, G.FramePeriod*1000);
  110. end
  111. if P.Debug && ~escape
  112. Nframes = size(timing,2);
  113. t = 1:Nframes;
  114. figure(1);
  115. timing(2:end,:) = 1000 * (timing(2:end,:) - repmat(timing(1,:), 3,1));
  116. plot(t,timing(2,:), 'ro-', t,timing(3,:),'go-', t,timing(4,:),'bo-');
  117. title('Timing Info (for debugging)');
  118. xlabel('Frame Number');
  119. ylabel('Delay (msec)');
  120. end