11function [cfg ] = initPTB(cfg )
22% This will initialize PsychToolBox
33% - screen
4- % - the windon opened takes the whole screen by default
5- % - set in debug mode with window transparency if necessary
6- % - can skip synch test if you ask for it (nicely)
7- % - gets the flip interval
8- % - computes the pixel per degree of visual angle
9- % - set font details
4+ % - the windon opened takes the whole screen unless
5+ % cfg.testingSmallScreen is set to true
6+ % - debug mode : skips synch test and warnings
7+ % - window transparency enabled by cfg.testingTranspScreen set to true
8+ % - gets the flip interval
9+ % - computes the pixel per degree of visual angle:
10+ % the computation for ppd assumes the windows takes the whole screenDistance
11+ % - set font details
1012% - keyboard
13+ % - hides cursor
1114% - sound
12-
15+ %
16+ % OUTPUT:
17+ % cfg.keyboard = [];
18+ % cfg.responseBox = [];
19+ %
20+ % cfg.debug = true;
21+ % cfg.testingTranspScreen = true;
22+ % cfg.testingSmallScreen = true;
23+ %
24+ % cfg.screen : screen numbers where drawing the stimulation (external screen if available)
25+ % cfg.win : window opened by PTB
26+ % cfg.winRect : window rectangule positiona and dimensions in pixel coordinates
27+ % cfg.winWidth : window width in pixels
28+ % cfg.winHeight : window height in pixels
29+ % cfg.center : coordinate of the window center
30+ % cfg.ppd : pixels per degree assuming the window fills the whole screen
31+ % cfg.ifi : estimate of the monitor flip interval
32+ % cfg.monRefresh : monitor refresh rate
33+ % cfg.vbl : (I don't think this output is useful)
34+ % cfg.textFont = 'Courier New';
35+ % cfg.textSize = 18;
36+ % cfg.textStyle = 1;
37+ % cfg.backgroundColor = [0 0 0];
38+ % cfg.monitorWidth = 42;
39+ % cfg.screenDistance = 134;
1340
1441% TO DO
1542% - We might want to add a couple of IF in case the experiment does not use audio for example.
16- % - the computation for ppd assumes the windows takes the whole screenDistance
17- % - refactor the window opening section (pass the window size as argument)
1843
19- checkDependencies()
2044
45+ checkDependencies()
2146
2247% For octave: to avoid displaying messenging one screen at a time
2348more off
2449
2550% check for OpenGL compatibility, abort otherwise:
2651AssertOpenGL ;
2752
53+ cfg = setDefaultsPTB(cfg );
2854
29- %% Keyboard
30- % Make sure keyboard mapping is the same on all supported operating systems
31- % Apple MacOS/X, MS-Windows and GNU/Linux:
32- KbName(' UnifyKeyNames' );
33-
34-
35-
36-
37- % ---------- FIX LATER ---------- %
38- % might be over agressive to test this at every PTB init maybe make it
39- % dependent on a debug "flag"
40-
41- testKeyboards(cfg )
55+ initDebug(cfg );
4256
43- % ---------- FIX LATER ---------- %
4457
45-
46-
47-
48- % Don't echo keypresses to Matlab window
49- ListenChar(-1 );
58+ %% Keyboard
59+ initKeyboard
5060
5161
5262%% Mouse
53- % Hide the mouse cursor:
5463HideCursor ;
5564
5665
57- %% Audio
58- % Intialize PsychPortAudio
59- InitializePsychSound( 1 );
66+ %% Audio
67+ cfg = initAudio( cfg );
68+
6069
6170
6271%% Visual
6372
6473% Get the screen numbers and draw to the external screen if avaliable
6574cfg.screen = max(Screen(' Screens' ));
6675
67- % init PTB with different options in concordance to the Debug Parameters
68- if cfg .debug
69-
70- % set to one because we don not care about time
71- Screen(' Preference' , ' SkipSyncTests' , 2 );
72- Screen(' Preference' , ' Verbosity' , 0 );
73- Screen(' Preferences' , ' SuppressAllWarnings' , 2 );
74-
75- if cfg .testingSmallScreen
76- [cfg .win , cfg .winRect ] = Screen(' OpenWindow' , cfg .screen , cfg .backgroundColor , [0 ,0 , 480 , 270 ]);
77- else
78- if cfg .testingTranspScreen
79- PsychDebugWindowConfiguration
80- end
81- [cfg .win , cfg .winRect ] = Screen(' OpenWindow' , cfg .screen , cfg .backgroundColor );
82- end
83-
84- else
85- Screen(' Preference' ,' SkipSyncTests' , 0 );
86- [cfg .win , cfg .winRect ] = Screen(' OpenWindow' , cfg .screen , cfg .backgroundColor );
87-
88- end
89-
76+ cfg = openWindow(cfg );
9077
9178% window size info
9279[cfg .winWidth , cfg .winHeight ] = WindowSize(cfg .win );
9380
94-
95-
96-
97- % ---------- FIX LATER ---------- %
98- % I don't think we want to hard code the 2/3 here. We might just add it to
99- % the Cfg structure
10081if strcmpi(cfg .stimPosition ,' scanner' )
10182 cfg .winRect(1 ,4 ) = cfg .winRect(1 ,4 )*2 / 3 ;
10283end
103- % ---------- FIX LATER ---------- %
104-
105-
106-
10784
10885% Get the Center of the Screen
10986cfg.center = [cfg .winRect(3 ), cfg .winRect(4 )]/2 ;
11087
11188% Computes the number of pixels per degree given the distance to screen and
11289% monitor width
113-
11490% This assumes that the window fills the whole screen
115- V = 2 *( 180 *(atan( cfg . monitorWidth /( 2 * cfg . screenDistance ))/ pi ) );
116- cfg.ppd = cfg .winRect(3 )/V ;
91+ FOV = computeFOV( cfg );
92+ cfg.ppd = cfg .winRect(3 )/FOV ;
11793
11894
119- % Enable alpha-blending, set it to a blend equation useable for linear
120- % superposition with alpha-weighted source.
121- Screen(' BlendFunction' , cfg .win , GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA );
122-
123-
124- %% Text and Font
125- % Select specific text font, style and size:
126- Screen(' TextFont' ,cfg .win , cfg .textFont );
127- Screen(' TextSize' ,cfg .win , cfg .textSize );
128- Screen(' TextStyle' , cfg .win , cfg .textStyle );
95+ %% Select specific text font, style and size
96+ initText(cfg )
12997
13098
13199%% Timing
152120
153121
154122end
123+
124+
125+ function initDebug(cfg )
126+
127+ % init PTB with different options in concordance to the debug Parameters
128+ Screen(' Preference' ,' SkipSyncTests' , 0 );
129+ if cfg .debug
130+
131+ Screen(' Preference' , ' SkipSyncTests' , 2 );
132+ Screen(' Preference' , ' Verbosity' , 0 );
133+ Screen(' Preferences' , ' SuppressAllWarnings' , 2 );
134+
135+ fprintf(' \n\n\n\n ' )
136+ fprintf(' ########################################\n ' )
137+ fprintf(' ## DEBUG MODE. TIMING WILL BE OFF. ##\n ' )
138+ fprintf(' ########################################' )
139+ fprintf(' \n\n\n\n ' )
140+
141+ testKeyboards(cfg )
142+
143+ end
144+
145+ if cfg .testingTranspScreen
146+ PsychDebugWindowConfiguration
147+ end
148+
149+ end
150+
151+ function initKeyboard
152+
153+ % Make sure keyboard mapping is the same on all supported operating systems
154+ % Apple MacOS/X, MS-Windows and GNU/Linux:
155+ KbName(' UnifyKeyNames' );
156+
157+ % Don't echo keypresses to Matlab window
158+ ListenChar(-1 );
159+
160+ end
161+
162+ function cfg = initAudio(cfg )
163+
164+ if cfg .initAudio
165+
166+ InitializePsychSound(1 );
167+
168+ cfg.audio.devIdx= [];
169+ cfg.audio.playbackMode = 1 ;
170+
171+ if isfield(cfg .audio , ' useDevice' )
172+
173+ % get audio device list
174+ audioDev = PsychPortAudio(' GetDevices' );
175+
176+ % find output device to use
177+ idx = find(...
178+ audioDev.NrInputChannels == cfg .audio .inputChannels && ...
179+ audioDev.NrOutputChannels == cfg .audio .channels && ...
180+ ~cellfun(@isempty , regexp({audioDev .HostAudioAPIName }, cfg .audio .deviceName )));
181+
182+ % save device ID
183+ cfg.audio.devIdx = audioDev(idx ).DeviceIndex;
184+
185+ % get device's sampling rate
186+ cfg.audio.fs = audioDev(idx ).DefaultSampleRate;
187+
188+ end
189+
190+ cfg.audio.pahandle = PsychPortAudio(' Open' , ...
191+ cfg .audio .devIdx , ...
192+ cfg .audio .playbackMode , ...
193+ cfg .audio .requestedLatency , ...
194+ cfg .audio .fs , ...
195+ cfg .audio .channels );
196+
197+ % set initial PTB volume for safety (participants can adjust this manually
198+ % at the begining of the experiment)
199+ PsychPortAudio(' Volume' , cfg .audio .pahandle , cfg .audio .initVolume );
200+
201+ cfg.audio.pushSize = cfg .audio .fs * 0.010 ; % ! push N ms only
202+
203+ cfg.audio.requestOffsetTime = 1 ; % offset 1 sec
204+ cfg.audio.reqsSampleOffset = cfg .audio .requestOffsetTime * cfg .audio .fs ;
205+
206+ end
207+ end
208+
209+ function cfg = openWindow(cfg )
210+
211+ if cfg .testingSmallScreen
212+ [cfg .win , cfg .winRect ] = Screen(' OpenWindow' , cfg .screen , cfg .backgroundColor , [0 ,0 , 480 , 270 ]);
213+ else
214+ [cfg .win , cfg .winRect ] = Screen(' OpenWindow' , cfg .screen , cfg .backgroundColor );
215+ end
216+
217+ % Enable alpha-blending, set it to a blend equation useable for linear
218+ % superposition with alpha-weighted source.
219+ Screen(' BlendFunction' , cfg .win , GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA );
220+
221+ end
222+
223+ function FOV = computeFOV(cfg )
224+
225+ % computes the number of degrees of visual angle in the whole field of view
226+ FOV = 2 *( 180 * ( atan( cfg .monitorWidth / (2 * cfg .screenDistance ) ) / pi ));
227+
228+ end
229+
230+
231+ function initText(cfg )
232+
233+ Screen(' TextFont' , cfg .win , cfg .textFont );
234+ Screen(' TextSize' , cfg .win , cfg .textSize );
235+ Screen(' TextStyle' , cfg .win , cfg .textStyle );
236+
237+ end
0 commit comments