fast-feedback virtual target task code on STM Nucleo

Dependencies:   mbed

Committer:
gwappa
Date:
Thu Jul 05 20:15:37 2018 +0000
Revision:
26:b4421d1ee57a
Parent:
24:e236faf66935
Child:
27:b31ea8d74f9e
transform event feature into the InterruptHandler class; organize files a little bit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gwappa 2:0c241937eabd 1 #include "trial.h"
gwappa 11:897ecd5413e0 2 #include "rig.h"
gwappa 2:0c241937eabd 3 #include "IO.h"
gwappa 2:0c241937eabd 4 #include "random.h"
gwappa 2:0c241937eabd 5
gwappa 11:897ecd5413e0 6 const uint64_t MicrosecondsInSecond = 1000000;
gwappa 11:897ecd5413e0 7
gwappa 20:4c06d3041337 8 inline uint64_t calc_blink_duration(const uint16_t& freq) {
gwappa 20:4c06d3041337 9 return (freq == 0)? 0 : (MicrosecondsInSecond/(freq * 2));
gwappa 20:4c06d3041337 10 }
gwappa 20:4c06d3041337 11
gwappa 20:4c06d3041337 12 void TrialFlag::clear() {
gwappa 19:50663f8815b8 13 cued = false;
gwappa 19:50663f8815b8 14 responded = false;
gwappa 19:50663f8815b8 15 reset = false;
gwappa 19:50663f8815b8 16 }
gwappa 19:50663f8815b8 17
gwappa 20:4c06d3041337 18 void TrialFlag::writeToSerial() {
gwappa 19:50663f8815b8 19 if (reset) {
gwappa 19:50663f8815b8 20 IO::write("reset");
gwappa 19:50663f8815b8 21 } else if (cued) {
gwappa 19:50663f8815b8 22 IO::write(responded? "hit":"miss");
gwappa 19:50663f8815b8 23 } else {
gwappa 19:50663f8815b8 24 IO::write(responded? "catch":"reject");
gwappa 19:50663f8815b8 25 }
gwappa 19:50663f8815b8 26 }
gwappa 19:50663f8815b8 27
gwappa 2:0c241937eabd 28 void Trial::reset(const Task& task){
gwappa 2:0c241937eabd 29 // reset score
gwappa 20:4c06d3041337 30 flag.clear();
gwappa 2:0c241937eabd 31
gwappa 2:0c241937eabd 32 // set delay duration
gwappa 5:849446d19406 33 delay_dur_ms = task.delay_min_ms.value
gwappa 5:849446d19406 34 + random::exponential(task.delay_var_ms.value, task.delay_var_ms.value*3);
gwappa 11:897ecd5413e0 35
gwappa 24:e236faf66935 36 // reset cues
gwappa 20:4c06d3041337 37 audioOut.setEnabled(false);
gwappa 15:20f7f737c256 38 visualOut.setEnabled(false);
gwappa 16:33c17c62840e 39 vis_dur_us = 0;
gwappa 16:33c17c62840e 40 vis_onset_us = 0;
gwappa 15:20f7f737c256 41
gwappa 24:e236faf66935 42 // configure reward
gwappa 24:e236faf66935 43 rewardOut.setOnset(0);
gwappa 24:e236faf66935 44 rewardOut.setDuration(ms_to_us(task.reward_dur_ms.value));
gwappa 24:e236faf66935 45
gwappa 24:e236faf66935 46 // configure cued state duration + visual stimulus position (if any)
gwappa 15:20f7f737c256 47 switch (task.mode.value) {
gwappa 15:20f7f737c256 48 case Pair:
gwappa 15:20f7f737c256 49 case Report:
gwappa 15:20f7f737c256 50 case Associate:
gwappa 24:e236faf66935 51 visualOut.setBlinkDuration( calc_blink_duration(task.vis_blink_hz.value) );
gwappa 24:e236faf66935 52 assignCues(task, true);
gwappa 24:e236faf66935 53 break;
gwappa 16:33c17c62840e 54 case Motion:
gwappa 16:33c17c62840e 55 case MotionAlt:
gwappa 24:e236faf66935 56 assignCues(task, false);
gwappa 24:e236faf66935 57 break;
gwappa 24:e236faf66935 58 }
gwappa 24:e236faf66935 59
gwappa 24:e236faf66935 60 // assign Auditory cues (if any)
gwappa 24:e236faf66935 61 switch (task.mode.value) {
gwappa 24:e236faf66935 62 case Pair:
gwappa 24:e236faf66935 63 case Report:
gwappa 24:e236faf66935 64 break;
gwappa 24:e236faf66935 65 case Associate:
gwappa 24:e236faf66935 66 case Motion:
gwappa 24:e236faf66935 67 case MotionAlt:
gwappa 24:e236faf66935 68 audioOut.setEnabled(true);
gwappa 24:e236faf66935 69 audioOut.setOnset(0);
gwappa 24:e236faf66935 70 audioOut.setDuration(cued_dur_us);
gwappa 24:e236faf66935 71 audioOut.setBlinkDuration( calc_blink_duration(task.aud_tick_hz.value) );
gwappa 15:20f7f737c256 72 break;
gwappa 13:8ea85a33e37a 73 }
gwappa 2:0c241937eabd 74
gwappa 3:991c6d5ce19d 75 // reset interrupt events
gwappa 26:b4421d1ee57a 76 lickIn.reset(task.lick_debounce_ms.value, true);
gwappa 26:b4421d1ee57a 77 whiskIn.reset(task.whisk_debounce_ms.value, true);
gwappa 26:b4421d1ee57a 78 gateIn.reset(-1, true);
gwappa 2:0c241937eabd 79 }
gwappa 2:0c241937eabd 80
gwappa 24:e236faf66935 81 void Trial::assignCues(const Task& task, const bool& assignVisual)
gwappa 13:8ea85a33e37a 82 {
gwappa 24:e236faf66935 83 if (!assignVisual) {
gwappa 24:e236faf66935 84 visualOut.setEnabled(false);
gwappa 24:e236faf66935 85 vis_dur_us = 0;
gwappa 24:e236faf66935 86 vis_onset_us = 0;
gwappa 24:e236faf66935 87
gwappa 24:e236faf66935 88 cued_dur_us = ms_to_us(task.aud_dur_ms.value);
gwappa 24:e236faf66935 89 return;
gwappa 24:e236faf66935 90 }
gwappa 24:e236faf66935 91
gwappa 13:8ea85a33e37a 92 const uint32_t phasedur_us = ms_to_us(task.aud_dur_ms.value);
gwappa 15:20f7f737c256 93 const uint32_t minonset_us = ms_to_us(task.pre_min_ms.value);
gwappa 13:8ea85a33e37a 94 const uint32_t respdur_us = ms_to_us(task.resp_dur_ms.value);
gwappa 14:af3adf5d5ddf 95 const uint32_t avgdur_us = ms_to_us(task.vis_avg_ms.value);
gwappa 13:8ea85a33e37a 96 const uint32_t mindur_us = ms_to_us(task.vis_min_ms.value);
gwappa 15:20f7f737c256 97 const double failure_perc = (task.vis_fail_perc.value > 0)? ((double)(task.vis_fail_perc.value)):1e-6;
gwappa 13:8ea85a33e37a 98
gwappa 20:4c06d3041337 99 const double onset_vrng = (double)(phasedur_us - minonset_us - respdur_us - mindur_us);
gwappa 20:4c06d3041337 100 const double logdecay = ::log(100.0) - ::log(failure_perc);
gwappa 20:4c06d3041337 101 const double ftau = onset_vrng/logdecay;
gwappa 14:af3adf5d5ddf 102 const uint32_t tau = (uint32_t)(ftau + 0.5);
gwappa 20:4c06d3041337 103 const uint32_t onset_us = random::exponential(tau, onset_vrng+10) + minonset_us;
gwappa 20:4c06d3041337 104 const uint32_t maxonset_us = onset_vrng + minonset_us;
gwappa 13:8ea85a33e37a 105
gwappa 20:4c06d3041337 106 if ((onset_us > 0) && (onset_us < maxonset_us)) {
gwappa 13:8ea85a33e37a 107 // generate duration
gwappa 20:4c06d3041337 108 const uint32_t dur_vrng = maxonset_us - onset_us;
gwappa 20:4c06d3041337 109 const uint32_t dur_us = random::exponential(avgdur_us - mindur_us, dur_vrng) + mindur_us;
gwappa 13:8ea85a33e37a 110
gwappa 15:20f7f737c256 111 visualOut.setEnabled(true);
gwappa 17:0b241aa1f5b6 112 visualOut.setDuration(dur_us);
gwappa 17:0b241aa1f5b6 113 visualOut.setOnset(onset_us);
gwappa 13:8ea85a33e37a 114
gwappa 17:0b241aa1f5b6 115 vis_dur_us = dur_us;
gwappa 17:0b241aa1f5b6 116 vis_onset_us = onset_us;
gwappa 24:e236faf66935 117
gwappa 24:e236faf66935 118 cued_dur_us = onset_us + dur_us + respdur_us;
gwappa 24:e236faf66935 119
gwappa 13:8ea85a33e37a 120 } else {
gwappa 15:20f7f737c256 121 // no pulse
gwappa 15:20f7f737c256 122 visualOut.setEnabled(false);
gwappa 16:33c17c62840e 123 vis_dur_us = 0;
gwappa 16:33c17c62840e 124 vis_onset_us = 0;
gwappa 24:e236faf66935 125
gwappa 24:e236faf66935 126 cued_dur_us = phasedur_us;
gwappa 13:8ea85a33e37a 127 }
gwappa 13:8ea85a33e37a 128 }
gwappa 13:8ea85a33e37a 129
gwappa 11:897ecd5413e0 130 void Trial::markTrialStart() {
gwappa 26:b4421d1ee57a 131 starting = TrialTimer.read_ms();
gwappa 12:06ea96546af1 132 trialStart.run();
gwappa 26:b4421d1ee57a 133 TrialTimer.start();
gwappa 11:897ecd5413e0 134 }
gwappa 11:897ecd5413e0 135
gwappa 11:897ecd5413e0 136 void Trial::markEndOfWait() {
gwappa 26:b4421d1ee57a 137 cuestarting = TrialTimer.read_ms();
gwappa 11:897ecd5413e0 138 waiting = cuestarting - starting;
gwappa 11:897ecd5413e0 139 }
gwappa 11:897ecd5413e0 140
gwappa 11:897ecd5413e0 141 void Trial::markTrialEnd() {
gwappa 12:06ea96546af1 142 trialEnd.run();
gwappa 11:897ecd5413e0 143 trialEnd.wait();
gwappa 11:897ecd5413e0 144 writeToSerial();
gwappa 26:b4421d1ee57a 145 TrialTimer.stop();
gwappa 26:b4421d1ee57a 146 TrialTimer.reset();
gwappa 11:897ecd5413e0 147 }
gwappa 11:897ecd5413e0 148
gwappa 2:0c241937eabd 149 void Trial::writeToSerial() {
gwappa 19:50663f8815b8 150 IO::write("%c",IO::RESULT_HEADER);
gwappa 19:50663f8815b8 151 flag.writeToSerial();
gwappa 2:0c241937eabd 152
gwappa 19:50663f8815b8 153 IO::write(";wait%u", waiting);
gwappa 13:8ea85a33e37a 154
gwappa 20:4c06d3041337 155 if (visualOut.isEnabled() && (!flag.reset)) {
gwappa 23:61af0317e404 156 IO::write(";visual(onset%s,duration%s)",
gwappa 23:61af0317e404 157 uint64_to_str(vis_onset_us).c_str(),
gwappa 23:61af0317e404 158 uint64_to_str(vis_dur_us).c_str());
gwappa 13:8ea85a33e37a 159 }
gwappa 13:8ea85a33e37a 160
gwappa 19:50663f8815b8 161 trialtime_t zero = (flag.reset)? starting : cuestarting;
gwappa 3:991c6d5ce19d 162 IO::write(";whisk");
gwappa 26:b4421d1ee57a 163 whiskIn.writeToSerial(zero);
gwappa 26:b4421d1ee57a 164 IO::write(";gate");
gwappa 26:b4421d1ee57a 165 gateIn.writeToSerial(zero);
gwappa 3:991c6d5ce19d 166 IO::write(";lick");
gwappa 26:b4421d1ee57a 167 lickIn.writeToSerial(zero);
gwappa 4:fcf597f82632 168 IO::write(";\r\n");
gwappa 2:0c241937eabd 169 }