fast-feedback virtual target task code on STM Nucleo

Dependencies:   mbed

Committer:
gwappa
Date:
Sun Oct 14 14:45:02 2018 +0000
Revision:
31:b320ca61a8c0
Parent:
30:5f975f572ffb
Child:
32:1416e015016c
up-to-date version

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 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 28:797536a42b9f 70 case Condition:
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 15:20f7f737c256 81 case Associate:
gwappa 29:1fb060aab1f8 82 assignAssociative(task);
gwappa 24:e236faf66935 83 break;
gwappa 16:33c17c62840e 84 case Motion:
gwappa 16:33c17c62840e 85 case MotionAlt:
gwappa 29:1fb060aab1f8 86 assignForFeedback(task);
gwappa 24:e236faf66935 87 break;
gwappa 24:e236faf66935 88 }
gwappa 24:e236faf66935 89
gwappa 24:e236faf66935 90 // assign Auditory cues (if any)
gwappa 24:e236faf66935 91 switch (task.mode.value) {
gwappa 28:797536a42b9f 92 case Condition:
gwappa 24:e236faf66935 93 case Report:
gwappa 24:e236faf66935 94 break;
gwappa 24:e236faf66935 95 case Associate:
gwappa 24:e236faf66935 96 case Motion:
gwappa 24:e236faf66935 97 case MotionAlt:
gwappa 24:e236faf66935 98 audioOut.setEnabled(true);
gwappa 24:e236faf66935 99 audioOut.setOnset(0);
gwappa 30:5f975f572ffb 100 audioOut.setDuration(ms_to_us(task.aud_dur_ms.value));
gwappa 24:e236faf66935 101 audioOut.setBlinkDuration( calc_blink_duration(task.aud_tick_hz.value) );
gwappa 15:20f7f737c256 102 break;
gwappa 13:8ea85a33e37a 103 }
gwappa 2:0c241937eabd 104
gwappa 3:991c6d5ce19d 105 // reset interrupt events
gwappa 26:b4421d1ee57a 106 lickIn.reset(task.lick_debounce_ms.value, true);
gwappa 26:b4421d1ee57a 107 whiskIn.reset(task.whisk_debounce_ms.value, true);
gwappa 26:b4421d1ee57a 108 gateIn.reset(-1, true);
gwappa 2:0c241937eabd 109 }
gwappa 2:0c241937eabd 110
gwappa 29:1fb060aab1f8 111 void Trial::assignForFeedback(const Task& task)
gwappa 13:8ea85a33e37a 112 {
gwappa 29:1fb060aab1f8 113 visualOut.setEnabled(false);
gwappa 29:1fb060aab1f8 114 visualOut.direct(true);
gwappa 29:1fb060aab1f8 115 vis_onset_us = 0;
gwappa 29:1fb060aab1f8 116 }
gwappa 29:1fb060aab1f8 117
gwappa 29:1fb060aab1f8 118 void Trial::assignAssociative(const Task& task)
gwappa 29:1fb060aab1f8 119 {
gwappa 29:1fb060aab1f8 120 const uint32_t phasedur_us = ms_to_us(task.aud_dur_ms.value);
gwappa 29:1fb060aab1f8 121 const uint32_t minonset_us = ms_to_us(task.onset_min_ms.value);
gwappa 29:1fb060aab1f8 122 const uint32_t respdur_us = ms_to_us(task.resp_dur_ms.value);
gwappa 29:1fb060aab1f8 123 const uint32_t visdur_us = ms_to_us(task.vis_dur_ms.value);
gwappa 13:8ea85a33e37a 124
gwappa 29:1fb060aab1f8 125 const double onset_vrng = (double)(phasedur_us - minonset_us - respdur_us - visdur_us);
gwappa 29:1fb060aab1f8 126 const uint16_t nsteps = task.onset_steps_n.value;
gwappa 29:1fb060aab1f8 127 const uint32_t onset_step = random::unif(nsteps);
gwappa 29:1fb060aab1f8 128
gwappa 29:1fb060aab1f8 129 vis_onset_us = (uint32_t)(onset_vrng*onset_step/nsteps);
gwappa 30:5f975f572ffb 130
gwappa 30:5f975f572ffb 131 visualOut.setEnabled(index > 0);
gwappa 30:5f975f572ffb 132 visualOut.setOnset(vis_onset_us);
gwappa 30:5f975f572ffb 133 visualOut.setDuration(ms_to_us(task.vis_dur_ms.value));
gwappa 13:8ea85a33e37a 134 }
gwappa 13:8ea85a33e37a 135
gwappa 11:897ecd5413e0 136 void Trial::markTrialStart() {
gwappa 26:b4421d1ee57a 137 starting = TrialTimer.read_ms();
gwappa 12:06ea96546af1 138 trialStart.run();
gwappa 26:b4421d1ee57a 139 TrialTimer.start();
gwappa 11:897ecd5413e0 140 }
gwappa 11:897ecd5413e0 141
gwappa 11:897ecd5413e0 142 void Trial::markEndOfWait() {
gwappa 26:b4421d1ee57a 143 cuestarting = TrialTimer.read_ms();
gwappa 11:897ecd5413e0 144 waiting = cuestarting - starting;
gwappa 11:897ecd5413e0 145 }
gwappa 11:897ecd5413e0 146
gwappa 29:1fb060aab1f8 147 void Trial::markTrialEnd(const Task& task) {
gwappa 12:06ea96546af1 148 trialEnd.run();
gwappa 11:897ecd5413e0 149 trialEnd.wait();
gwappa 29:1fb060aab1f8 150 writeToSerial(task);
gwappa 26:b4421d1ee57a 151 TrialTimer.stop();
gwappa 26:b4421d1ee57a 152 TrialTimer.reset();
gwappa 27:b31ea8d74f9e 153 visualOut.direct(false); // if any
gwappa 31:b320ca61a8c0 154
gwappa 31:b320ca61a8c0 155 if (!flag.reset) {
gwappa 31:b320ca61a8c0 156 index++;
gwappa 31:b320ca61a8c0 157 }
gwappa 11:897ecd5413e0 158 }
gwappa 11:897ecd5413e0 159
gwappa 29:1fb060aab1f8 160 void Trial::writeToSerial(const Task& task) {
gwappa 19:50663f8815b8 161 IO::write("%c",IO::RESULT_HEADER);
gwappa 29:1fb060aab1f8 162 flag.writeToSerial(task);
gwappa 2:0c241937eabd 163
gwappa 30:5f975f572ffb 164 IO::write(";index%u;wait%u", index, waiting);
gwappa 13:8ea85a33e37a 165
gwappa 31:b320ca61a8c0 166 if (task.mode.value == Associate) {
gwappa 31:b320ca61a8c0 167 if ((visualOut.isEnabled()) && (!flag.reset)) {
gwappa 31:b320ca61a8c0 168 IO::write(";visual%u",(vis_onset_us/1000));
gwappa 31:b320ca61a8c0 169 }
gwappa 13:8ea85a33e37a 170 }
gwappa 13:8ea85a33e37a 171
gwappa 19:50663f8815b8 172 trialtime_t zero = (flag.reset)? starting : cuestarting;
gwappa 3:991c6d5ce19d 173 IO::write(";whisk");
gwappa 26:b4421d1ee57a 174 whiskIn.writeToSerial(zero);
gwappa 26:b4421d1ee57a 175 IO::write(";gate");
gwappa 26:b4421d1ee57a 176 gateIn.writeToSerial(zero);
gwappa 3:991c6d5ce19d 177 IO::write(";lick");
gwappa 26:b4421d1ee57a 178 lickIn.writeToSerial(zero);
gwappa 4:fcf597f82632 179 IO::write(";\r\n");
gwappa 2:0c241937eabd 180 }