Hi Taylor,
We just tried your solution of moving start_io_device (laser) earlier and it did reduce the delay. The laser was turned on before the stimulus was on but still ended a bit earlier than the stimulus off. But both the laser and the stimulus were on for the intended 300ms.
It’s going to be hard to align the laser and stimulus timing precisely if you use pulse
to control the laser (as you do in macro turn_laser_on
). It’d be much easier if you performed laser on/off synchronously, in states “Stimulus On” and “Stim success”. Here’s the gist of what I’m suggesting in MWEL:
state 'Stimulus On' {
// Already did start_io_device(laser) earlier in the trial
queue_stimulus(target_stimulus[stimulus_type])
photodiode_pixel_on()
update_display (predicted_output_time = predicted_display_update_time)
// laser_padding_time is the desired interval between laser on and
// stimulus on -- maybe a few milliseconds?
wait (predicted_display_update_time - laser_padding_time - now())
vpixx_dout_laser_gate = true
vpixx_send_blackrock_sync_word(e_laser_on)
wait (predicted_display_update_time - now())
// We've reached the point where we expect the stimulus to actually be
// on, so start the timer and send e_stimulus_on here
start_timer (timer = timer2; duration = stimulus_on_duration)
vpixx_send_blackrock_sync_word(e_stimulus_on)
vpixx_send_blackrock_sync_word(e_photodiode_on)
goto (target = 'Stim success'; when = timer_expired(timer2))
goto (target = 'Broke Central Fixation'; when = not eye_in_fixation)
}
state 'Stim success' {
dequeue_stimulus(target_stimulus[stimulus_type])
photodiode_pixel_off()
update_display (predicted_output_time = predicted_display_update_time)
wait (predicted_display_update_time - now())
// The stimuli should be off now
vpixx_send_blackrock_sync_word(e_stimulus_off)
vpixx_send_blackrock_sync_word(e_photodiode_off)
wait (laser_padding_time)
vpixx_dout_laser_gate = false
vpixx_send_blackrock_sync_word(e_laser_off)
stop_io_device (laser)
//...
}
State “Broke Central Fixation” already has code for turning the laser off, so you don’t need to add it there. Does this make sense?
Since the configuration of the laser is now in the non-timing-critical portion of the protocol, the time it takes the laser to configure (~60ms) shouldn’t make the length of the trials with laser on 60ms longer than the length of the trials without laser, correct?
If, in the “laser off” trials, you didn’t configure the laser (i.e you didn’t call start_io_device
), then those trials would be ~60ms shorter than trials with the laser on. But looking at your code, I see that even when laser_type
is set to 0 (“off”), you still configure and activate the laser as usual – it’s just that in this case, “active” means all channels off. This means that you’re still doing the same amount of laser configuration, so the trial length should be the same.
That said, it still might be wise to move start_io_device
completely out of any timed portion of the trial – perhaps all the way back in “Begin Trial”? This would protect against any variability in the time it takes to configure the laser. As I noted previously, you have to set all laser parameters before calling start_io_device
, so you’d need to move that code back, too.
Cheers,
Chris