Keisuke Sehara
/
STM32_Whisking
fast-feedback virtual target task code on STM Nucleo
trial.cpp
- Committer:
- gwappa
- Date:
- 2018-07-05
- Revision:
- 26:b4421d1ee57a
- Parent:
- 24:e236faf66935
- Child:
- 27:b31ea8d74f9e
File content as of revision 26:b4421d1ee57a:
#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; reset = false; } void TrialFlag::writeToSerial() { 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){ // 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_dur_us = 0; 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: case Report: case Associate: visualOut.setBlinkDuration( calc_blink_duration(task.vis_blink_hz.value) ); assignCues(task, true); break; case Motion: case MotionAlt: assignCues(task, false); break; } // assign Auditory cues (if any) switch (task.mode.value) { case Pair: case Report: break; case Associate: case Motion: case MotionAlt: audioOut.setEnabled(true); audioOut.setOnset(0); audioOut.setDuration(cued_dur_us); 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::assignCues(const Task& task, const bool& assignVisual) { if (!assignVisual) { visualOut.setEnabled(false); vis_dur_us = 0; vis_onset_us = 0; cued_dur_us = ms_to_us(task.aud_dur_ms.value); return; } const uint32_t phasedur_us = ms_to_us(task.aud_dur_ms.value); const uint32_t minonset_us = ms_to_us(task.pre_min_ms.value); const uint32_t respdur_us = ms_to_us(task.resp_dur_ms.value); const uint32_t avgdur_us = ms_to_us(task.vis_avg_ms.value); const uint32_t mindur_us = ms_to_us(task.vis_min_ms.value); const double failure_perc = (task.vis_fail_perc.value > 0)? ((double)(task.vis_fail_perc.value)):1e-6; const double onset_vrng = (double)(phasedur_us - minonset_us - respdur_us - mindur_us); const double logdecay = ::log(100.0) - ::log(failure_perc); const double ftau = onset_vrng/logdecay; const uint32_t tau = (uint32_t)(ftau + 0.5); const uint32_t onset_us = random::exponential(tau, onset_vrng+10) + minonset_us; const uint32_t maxonset_us = onset_vrng + minonset_us; if ((onset_us > 0) && (onset_us < maxonset_us)) { // generate duration const uint32_t dur_vrng = maxonset_us - onset_us; const uint32_t dur_us = random::exponential(avgdur_us - mindur_us, dur_vrng) + mindur_us; visualOut.setEnabled(true); visualOut.setDuration(dur_us); visualOut.setOnset(onset_us); vis_dur_us = dur_us; vis_onset_us = onset_us; cued_dur_us = onset_us + dur_us + respdur_us; } else { // no pulse visualOut.setEnabled(false); vis_dur_us = 0; vis_onset_us = 0; cued_dur_us = phasedur_us; } } void Trial::markTrialStart() { starting = TrialTimer.read_ms(); trialStart.run(); TrialTimer.start(); } void Trial::markEndOfWait() { cuestarting = TrialTimer.read_ms(); waiting = cuestarting - starting; } void Trial::markTrialEnd() { trialEnd.run(); trialEnd.wait(); writeToSerial(); TrialTimer.stop(); TrialTimer.reset(); } void Trial::writeToSerial() { IO::write("%c",IO::RESULT_HEADER); flag.writeToSerial(); IO::write(";wait%u", waiting); if (visualOut.isEnabled() && (!flag.reset)) { IO::write(";visual(onset%s,duration%s)", uint64_to_str(vis_onset_us).c_str(), uint64_to_str(vis_dur_us).c_str()); } 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"); }