Keisuke Sehara
/
STM32_Whisking
fast-feedback virtual target task code on STM Nucleo
trial.cpp
- Committer:
- gwappa
- Date:
- 2018-12-13
- Revision:
- 32:1416e015016c
- Parent:
- 31:b320ca61a8c0
File content as of revision 32:1416e015016c:
#include "trial.h" #include "rig.h" #include "IO.h" #include "random.h" const uint64_t MicrosecondsInSecond = 1000000; inline uint64_t calc_blink_duration(const uint16_t& freq) { return (freq == 0)? 0 : (MicrosecondsInSecond/(freq * 2)); } void TrialFlag::clear() { cued = false; responded = false; rewarded = false; reset = false; } void TrialFlag::writeToSerial(const Task& task) { if (task.mode.value == Pair) { if (reset) { IO::write("reset"); } else if (rewarded) { IO::write(responded? "resp":"noresp"); } else { IO::write(responded? "hit":"miss"); } } else { if (reset) { IO::write("reset"); } else if (cued) { IO::write(responded? "hit":"miss"); } else { IO::write(responded? "catch":"reject"); } } } void Trial::reset(const Task& task){ if (task.vis_test_every.value > 0) { index = index % task.vis_test_every.value; } else { if (index == 101) { index = 1; } } // reset score flag.clear(); // set delay duration delay_dur_ms = task.delay_min_ms.value + random::exponential(task.delay_var_ms.value, task.delay_var_ms.value*3); // reset cues audioOut.setEnabled(false); visualOut.setEnabled(false); vis_onset_us = 0; // configure reward rewardOut.setOnset(0); rewardOut.setDuration(ms_to_us(task.reward_dur_ms.value)); // configure cued state duration + visual stimulus position (if any) switch (task.mode.value) { case Pair: flag.rewarded = (index > 0); visualOut.setEnabled(true); visualOut.setOnset(0); visualOut.setDuration(ms_to_us(task.vis_dur_ms.value)); break; case Report: visualOut.setEnabled(index > 0); visualOut.setOnset(0); visualOut.setDuration(ms_to_us(task.vis_dur_ms.value)); break; case Stage: case Associate: assignAssociative(task); break; case Motion: case MotionAlt: assignForFeedback(task); break; } // assign Auditory cues (if any) switch (task.mode.value) { case Pair: case Report: break; case Stage: case Associate: case Motion: case MotionAlt: audioOut.setEnabled(true); audioOut.setOnset(0); audioOut.setDuration(ms_to_us(task.aud_dur_ms.value)); audioOut.setBlinkDuration( calc_blink_duration(task.aud_tick_hz.value) ); break; } // reset interrupt events lickIn.reset(task.lick_debounce_ms.value, true); whiskIn.reset(task.whisk_debounce_ms.value, true); gateIn.reset(-1, true); } void Trial::assignForFeedback(const Task& task) { visualOut.setEnabled(false); visualOut.direct(true); vis_onset_us = 0; } void Trial::assignAssociative(const Task& task) { const uint32_t phasedur_us = ms_to_us(task.aud_dur_ms.value); const uint32_t minonset_us = ms_to_us(task.onset_min_ms.value); const uint32_t respdur_us = ms_to_us(task.resp_dur_ms.value); const uint32_t visdur_us = ms_to_us(task.vis_dur_ms.value); const double onset_vrng = (double)(phasedur_us - minonset_us - respdur_us - visdur_us); const uint16_t nsteps = task.onset_steps_n.value; const uint32_t onset_step = random::unif(nsteps); vis_onset_us = (uint32_t)((onset_vrng*onset_step/nsteps) + minonset_us); visualOut.setEnabled(index > 0); visualOut.setOnset(vis_onset_us); visualOut.setDuration(ms_to_us(task.vis_dur_ms.value)); } void Trial::markTrialStart() { starting = TrialTimer.read_ms(); trialStart.run(); TrialTimer.start(); } void Trial::markEndOfWait() { cuestarting = TrialTimer.read_ms(); waiting = cuestarting - starting; } void Trial::markTrialEnd(const Task& task) { trialEnd.run(); trialEnd.wait(); writeToSerial(task); TrialTimer.stop(); TrialTimer.reset(); visualOut.direct(false); // if any if (!flag.reset) { index++; } } void Trial::writeToSerial(const Task& task) { IO::write("%c",IO::RESULT_HEADER); flag.writeToSerial(task); IO::write(";index%u;wait%u", index, waiting); switch (task.mode.value) { case Stage: case Associate: if ((visualOut.isEnabled()) && (!flag.reset)) { IO::write(";visual%u",(uint16_t)(vis_onset_us/1000)); } } trialtime_t zero = (flag.reset)? starting : cuestarting; IO::write(";whisk"); whiskIn.writeToSerial(zero); IO::write(";gate"); gateIn.writeToSerial(zero); IO::write(";lick"); lickIn.writeToSerial(zero); IO::write(";\r\n"); }