fast-feedback virtual target task code on STM Nucleo

Dependencies:   mbed

Committer:
gwappa
Date:
Mon Oct 01 15:16:04 2018 +0000
Revision:
30:5f975f572ffb
Parent:
29:1fb060aab1f8
Child:
31:b320ca61a8c0
add trial index for test trials

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