fast-feedback virtual target task code on STM Nucleo

Dependencies:   mbed

Committer:
gwappa
Date:
Thu Dec 13 07:18:43 2018 +0000
Revision:
32:1416e015016c
Parent:
31:b320ca61a8c0
change to use the Staged state

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 29:1fb060aab1f8 15 rewarded = false;
gwappa 19:50663f8815b8 16 reset = false;
gwappa 19:50663f8815b8 17 }
gwappa 19:50663f8815b8 18
gwappa 29:1fb060aab1f8 19 void TrialFlag::writeToSerial(const Task& task) {
gwappa 32:1416e015016c 20 if (task.mode.value == Pair)
gwappa 29:1fb060aab1f8 21 {
gwappa 31:b320ca61a8c0 22 if (reset) {
gwappa 31:b320ca61a8c0 23 IO::write("reset");
gwappa 31:b320ca61a8c0 24 } else if (rewarded) {
gwappa 29:1fb060aab1f8 25 IO::write(responded? "resp":"noresp");
gwappa 29:1fb060aab1f8 26 } else {
gwappa 29:1fb060aab1f8 27 IO::write(responded? "hit":"miss");
gwappa 29:1fb060aab1f8 28 }
gwappa 29:1fb060aab1f8 29 }
gwappa 29:1fb060aab1f8 30 else
gwappa 29:1fb060aab1f8 31 {
gwappa 29:1fb060aab1f8 32 if (reset) {
gwappa 29:1fb060aab1f8 33 IO::write("reset");
gwappa 29:1fb060aab1f8 34 } else if (cued) {
gwappa 29:1fb060aab1f8 35 IO::write(responded? "hit":"miss");
gwappa 29:1fb060aab1f8 36 } else {
gwappa 29:1fb060aab1f8 37 IO::write(responded? "catch":"reject");
gwappa 29:1fb060aab1f8 38 }
gwappa 19:50663f8815b8 39 }
gwappa 19:50663f8815b8 40 }
gwappa 19:50663f8815b8 41
gwappa 2:0c241937eabd 42 void Trial::reset(const Task& task){
gwappa 30:5f975f572ffb 43
gwappa 30:5f975f572ffb 44 if (task.vis_test_every.value > 0) {
gwappa 31:b320ca61a8c0 45 index = index % task.vis_test_every.value;
gwappa 30:5f975f572ffb 46 } else {
gwappa 30:5f975f572ffb 47 if (index == 101) {
gwappa 30:5f975f572ffb 48 index = 1;
gwappa 30:5f975f572ffb 49 }
gwappa 30:5f975f572ffb 50 }
gwappa 30:5f975f572ffb 51
gwappa 2:0c241937eabd 52 // reset score
gwappa 20:4c06d3041337 53 flag.clear();
gwappa 2:0c241937eabd 54
gwappa 2:0c241937eabd 55 // set delay duration
gwappa 5:849446d19406 56 delay_dur_ms = task.delay_min_ms.value
gwappa 5:849446d19406 57 + random::exponential(task.delay_var_ms.value, task.delay_var_ms.value*3);
gwappa 11:897ecd5413e0 58
gwappa 24:e236faf66935 59 // reset cues
gwappa 20:4c06d3041337 60 audioOut.setEnabled(false);
gwappa 15:20f7f737c256 61 visualOut.setEnabled(false);
gwappa 16:33c17c62840e 62 vis_onset_us = 0;
gwappa 15:20f7f737c256 63
gwappa 24:e236faf66935 64 // configure reward
gwappa 24:e236faf66935 65 rewardOut.setOnset(0);
gwappa 24:e236faf66935 66 rewardOut.setDuration(ms_to_us(task.reward_dur_ms.value));
gwappa 24:e236faf66935 67
gwappa 24:e236faf66935 68 // configure cued state duration + visual stimulus position (if any)
gwappa 15:20f7f737c256 69 switch (task.mode.value) {
gwappa 32:1416e015016c 70 case Pair:
gwappa 30:5f975f572ffb 71 flag.rewarded = (index > 0);
gwappa 30:5f975f572ffb 72 visualOut.setEnabled(true);
gwappa 30:5f975f572ffb 73 visualOut.setOnset(0);
gwappa 30:5f975f572ffb 74 visualOut.setDuration(ms_to_us(task.vis_dur_ms.value));
gwappa 30:5f975f572ffb 75 break;
gwappa 29:1fb060aab1f8 76 case Report:
gwappa 30:5f975f572ffb 77 visualOut.setEnabled(index > 0);
gwappa 29:1fb060aab1f8 78 visualOut.setOnset(0);
gwappa 29:1fb060aab1f8 79 visualOut.setDuration(ms_to_us(task.vis_dur_ms.value));
gwappa 28:797536a42b9f 80 break;
gwappa 32:1416e015016c 81 case Stage:
gwappa 15:20f7f737c256 82 case Associate:
gwappa 29:1fb060aab1f8 83 assignAssociative(task);
gwappa 24:e236faf66935 84 break;
gwappa 16:33c17c62840e 85 case Motion:
gwappa 16:33c17c62840e 86 case MotionAlt:
gwappa 29:1fb060aab1f8 87 assignForFeedback(task);
gwappa 24:e236faf66935 88 break;
gwappa 24:e236faf66935 89 }
gwappa 24:e236faf66935 90
gwappa 24:e236faf66935 91 // assign Auditory cues (if any)
gwappa 24:e236faf66935 92 switch (task.mode.value) {
gwappa 32:1416e015016c 93 case Pair:
gwappa 24:e236faf66935 94 case Report:
gwappa 24:e236faf66935 95 break;
gwappa 32:1416e015016c 96 case Stage:
gwappa 24:e236faf66935 97 case Associate:
gwappa 24:e236faf66935 98 case Motion:
gwappa 24:e236faf66935 99 case MotionAlt:
gwappa 24:e236faf66935 100 audioOut.setEnabled(true);
gwappa 24:e236faf66935 101 audioOut.setOnset(0);
gwappa 30:5f975f572ffb 102 audioOut.setDuration(ms_to_us(task.aud_dur_ms.value));
gwappa 24:e236faf66935 103 audioOut.setBlinkDuration( calc_blink_duration(task.aud_tick_hz.value) );
gwappa 15:20f7f737c256 104 break;
gwappa 13:8ea85a33e37a 105 }
gwappa 2:0c241937eabd 106
gwappa 3:991c6d5ce19d 107 // reset interrupt events
gwappa 26:b4421d1ee57a 108 lickIn.reset(task.lick_debounce_ms.value, true);
gwappa 26:b4421d1ee57a 109 whiskIn.reset(task.whisk_debounce_ms.value, true);
gwappa 26:b4421d1ee57a 110 gateIn.reset(-1, true);
gwappa 2:0c241937eabd 111 }
gwappa 2:0c241937eabd 112
gwappa 29:1fb060aab1f8 113 void Trial::assignForFeedback(const Task& task)
gwappa 13:8ea85a33e37a 114 {
gwappa 29:1fb060aab1f8 115 visualOut.setEnabled(false);
gwappa 29:1fb060aab1f8 116 visualOut.direct(true);
gwappa 29:1fb060aab1f8 117 vis_onset_us = 0;
gwappa 29:1fb060aab1f8 118 }
gwappa 29:1fb060aab1f8 119
gwappa 29:1fb060aab1f8 120 void Trial::assignAssociative(const Task& task)
gwappa 29:1fb060aab1f8 121 {
gwappa 29:1fb060aab1f8 122 const uint32_t phasedur_us = ms_to_us(task.aud_dur_ms.value);
gwappa 29:1fb060aab1f8 123 const uint32_t minonset_us = ms_to_us(task.onset_min_ms.value);
gwappa 29:1fb060aab1f8 124 const uint32_t respdur_us = ms_to_us(task.resp_dur_ms.value);
gwappa 29:1fb060aab1f8 125 const uint32_t visdur_us = ms_to_us(task.vis_dur_ms.value);
gwappa 13:8ea85a33e37a 126
gwappa 29:1fb060aab1f8 127 const double onset_vrng = (double)(phasedur_us - minonset_us - respdur_us - visdur_us);
gwappa 29:1fb060aab1f8 128 const uint16_t nsteps = task.onset_steps_n.value;
gwappa 29:1fb060aab1f8 129 const uint32_t onset_step = random::unif(nsteps);
gwappa 29:1fb060aab1f8 130
gwappa 32:1416e015016c 131 vis_onset_us = (uint32_t)((onset_vrng*onset_step/nsteps) + minonset_us);
gwappa 30:5f975f572ffb 132
gwappa 30:5f975f572ffb 133 visualOut.setEnabled(index > 0);
gwappa 30:5f975f572ffb 134 visualOut.setOnset(vis_onset_us);
gwappa 30:5f975f572ffb 135 visualOut.setDuration(ms_to_us(task.vis_dur_ms.value));
gwappa 13:8ea85a33e37a 136 }
gwappa 13:8ea85a33e37a 137
gwappa 11:897ecd5413e0 138 void Trial::markTrialStart() {
gwappa 26:b4421d1ee57a 139 starting = TrialTimer.read_ms();
gwappa 12:06ea96546af1 140 trialStart.run();
gwappa 26:b4421d1ee57a 141 TrialTimer.start();
gwappa 11:897ecd5413e0 142 }
gwappa 11:897ecd5413e0 143
gwappa 11:897ecd5413e0 144 void Trial::markEndOfWait() {
gwappa 26:b4421d1ee57a 145 cuestarting = TrialTimer.read_ms();
gwappa 11:897ecd5413e0 146 waiting = cuestarting - starting;
gwappa 11:897ecd5413e0 147 }
gwappa 11:897ecd5413e0 148
gwappa 29:1fb060aab1f8 149 void Trial::markTrialEnd(const Task& task) {
gwappa 12:06ea96546af1 150 trialEnd.run();
gwappa 11:897ecd5413e0 151 trialEnd.wait();
gwappa 29:1fb060aab1f8 152 writeToSerial(task);
gwappa 26:b4421d1ee57a 153 TrialTimer.stop();
gwappa 26:b4421d1ee57a 154 TrialTimer.reset();
gwappa 27:b31ea8d74f9e 155 visualOut.direct(false); // if any
gwappa 31:b320ca61a8c0 156
gwappa 31:b320ca61a8c0 157 if (!flag.reset) {
gwappa 31:b320ca61a8c0 158 index++;
gwappa 31:b320ca61a8c0 159 }
gwappa 11:897ecd5413e0 160 }
gwappa 11:897ecd5413e0 161
gwappa 29:1fb060aab1f8 162 void Trial::writeToSerial(const Task& task) {
gwappa 19:50663f8815b8 163 IO::write("%c",IO::RESULT_HEADER);
gwappa 29:1fb060aab1f8 164 flag.writeToSerial(task);
gwappa 2:0c241937eabd 165
gwappa 30:5f975f572ffb 166 IO::write(";index%u;wait%u", index, waiting);
gwappa 13:8ea85a33e37a 167
gwappa 32:1416e015016c 168 switch (task.mode.value) {
gwappa 32:1416e015016c 169 case Stage:
gwappa 32:1416e015016c 170 case Associate:
gwappa 31:b320ca61a8c0 171 if ((visualOut.isEnabled()) && (!flag.reset)) {
gwappa 32:1416e015016c 172 IO::write(";visual%u",(uint16_t)(vis_onset_us/1000));
gwappa 31:b320ca61a8c0 173 }
gwappa 13:8ea85a33e37a 174 }
gwappa 13:8ea85a33e37a 175
gwappa 19:50663f8815b8 176 trialtime_t zero = (flag.reset)? starting : cuestarting;
gwappa 3:991c6d5ce19d 177 IO::write(";whisk");
gwappa 26:b4421d1ee57a 178 whiskIn.writeToSerial(zero);
gwappa 26:b4421d1ee57a 179 IO::write(";gate");
gwappa 26:b4421d1ee57a 180 gateIn.writeToSerial(zero);
gwappa 3:991c6d5ce19d 181 IO::write(";lick");
gwappa 26:b4421d1ee57a 182 lickIn.writeToSerial(zero);
gwappa 4:fcf597f82632 183 IO::write(";\r\n");
gwappa 2:0c241937eabd 184 }