fast-feedback virtual target task code on STM Nucleo

Dependencies:   mbed

Committer:
gwappa
Date:
Mon Jul 02 08:26:44 2018 +0000
Revision:
19:50663f8815b8
Parent:
17:0b241aa1f5b6
Child:
20:4c06d3041337
try changing the flag system over to a set of booleans

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gwappa 4:fcf597f82632 1 #include "states.h"
gwappa 4:fcf597f82632 2 #include "rig.h"
gwappa 4:fcf597f82632 3 #include "automaton.h"
gwappa 12:06ea96546af1 4 #include "events.h"
gwappa 4:fcf597f82632 5 #include "IO.h"
gwappa 4:fcf597f82632 6
gwappa 4:fcf597f82632 7 #define STATE_IS_LOGGED
gwappa 4:fcf597f82632 8
gwappa 4:fcf597f82632 9 #ifdef STATE_IS_LOGGED
gwappa 4:fcf597f82632 10 #define LOGSTATE(S) IO::info(#S);
gwappa 4:fcf597f82632 11 #else
gwappa 4:fcf597f82632 12 #define LOGSTATE(S)
gwappa 4:fcf597f82632 13 #endif
gwappa 4:fcf597f82632 14
gwappa 11:897ecd5413e0 15 void tickBuzzer() {
gwappa 11:897ecd5413e0 16 audioOut = !audioOut;
gwappa 9:e136394bdb39 17 }
gwappa 9:e136394bdb39 18
gwappa 4:fcf597f82632 19 void finalize() {
gwappa 11:897ecd5413e0 20 audioOut.write(0); // if any
gwappa 11:897ecd5413e0 21 trial.markTrialEnd();
gwappa 4:fcf597f82632 22 }
gwappa 4:fcf597f82632 23
gwappa 4:fcf597f82632 24 void Delay::setup() {
gwappa 4:fcf597f82632 25 LOGSTATE(Delay)
gwappa 4:fcf597f82632 26
gwappa 4:fcf597f82632 27 // initialize the trial-related params
gwappa 4:fcf597f82632 28 trial.reset(task);
gwappa 11:897ecd5413e0 29 audioOut.write(0);
gwappa 12:06ea96546af1 30 events::setup(true);
gwappa 4:fcf597f82632 31
gwappa 11:897ecd5413e0 32 // set up the timeout for the next state
gwappa 9:e136394bdb39 33 switch (task.mode.value) {
gwappa 9:e136394bdb39 34 case Pair:
gwappa 9:e136394bdb39 35 stateTimeout.attach_us(&automaton::jump<Delay,Paired>, ms_to_us(trial.delay_dur_ms + task.prep_dur_ms.value));
gwappa 9:e136394bdb39 36 break;
gwappa 16:33c17c62840e 37 case MotionAlt:
gwappa 16:33c17c62840e 38 stateTimeout.attach_us(&automaton::jump<Delay,Cued>, ms_to_us(trial.delay_dur_ms + task.prep_dur_ms.value));
gwappa 16:33c17c62840e 39 break;
gwappa 9:e136394bdb39 40 default:
gwappa 7:6744ec9ccc25 41 stateTimeout.attach_us(&automaton::jump<Delay,Prepare>, ms_to_us(trial.delay_dur_ms));
gwappa 7:6744ec9ccc25 42 }
gwappa 4:fcf597f82632 43
gwappa 11:897ecd5413e0 44 trial.markTrialStart();
gwappa 4:fcf597f82632 45 }
gwappa 4:fcf597f82632 46
gwappa 4:fcf597f82632 47 void Delay::teardown() {
gwappa 4:fcf597f82632 48 // do nothing
gwappa 4:fcf597f82632 49 }
gwappa 4:fcf597f82632 50
gwappa 11:897ecd5413e0 51 void Paired::setup() {
gwappa 11:897ecd5413e0 52 LOGSTATE(Paired)
gwappa 11:897ecd5413e0 53 trial.markEndOfWait();
gwappa 11:897ecd5413e0 54
gwappa 19:50663f8815b8 55 events::gatehandler = &Paired::gate;
gwappa 12:06ea96546af1 56 events::lickhandler = &automaton::jump<Paired,WithResp>;
gwappa 11:897ecd5413e0 57
gwappa 11:897ecd5413e0 58 // reward & visual feedback
gwappa 15:20f7f737c256 59 visualOut.start();
gwappa 11:897ecd5413e0 60 rewardOut.start();
gwappa 11:897ecd5413e0 61
gwappa 11:897ecd5413e0 62 stateTimeout.attach_us(&automaton::jump<Paired,NoResp>, ms_to_us(task.aud_dur_ms.value));
gwappa 11:897ecd5413e0 63 }
gwappa 11:897ecd5413e0 64
gwappa 19:50663f8815b8 65 void Paired::gate() {
gwappa 19:50663f8815b8 66 events::gatehandler = 0;
gwappa 19:50663f8815b8 67 events::whiskhandler = 0;
gwappa 19:50663f8815b8 68 trial.flag.cued = true;
gwappa 19:50663f8815b8 69 events::lickhandler = &automaton::jump<Cued,WithResp>;
gwappa 19:50663f8815b8 70 }
gwappa 19:50663f8815b8 71
gwappa 11:897ecd5413e0 72 void Paired::teardown() {
gwappa 15:20f7f737c256 73 visualOut.stop();
gwappa 19:50663f8815b8 74 events::gatehandler = 0;
gwappa 12:06ea96546af1 75 events::lickhandler = 0;
gwappa 11:897ecd5413e0 76 }
gwappa 11:897ecd5413e0 77
gwappa 7:6744ec9ccc25 78 void Prepare::setup() {
gwappa 7:6744ec9ccc25 79 // mostly the same with for Delay
gwappa 7:6744ec9ccc25 80 // except that the animal cannot lick freely
gwappa 7:6744ec9ccc25 81 LOGSTATE(Prepare)
gwappa 7:6744ec9ccc25 82
gwappa 7:6744ec9ccc25 83 // configure the interrupts
gwappa 12:06ea96546af1 84 // no whisk handler
gwappa 12:06ea96546af1 85 events::lickhandler = &automaton::jump<Prepare,Abort>;
gwappa 7:6744ec9ccc25 86
gwappa 7:6744ec9ccc25 87 // set timeout for the next state
gwappa 7:6744ec9ccc25 88 stateTimeout.attach_us(&automaton::jump<Prepare,Cued>, ms_to_us(task.prep_dur_ms.value));
gwappa 7:6744ec9ccc25 89 }
gwappa 7:6744ec9ccc25 90
gwappa 7:6744ec9ccc25 91 void Prepare::teardown() {
gwappa 7:6744ec9ccc25 92 // de-register lick inhibition
gwappa 12:06ea96546af1 93 events::lickhandler = 0;
gwappa 9:e136394bdb39 94 }
gwappa 9:e136394bdb39 95
gwappa 4:fcf597f82632 96 void Cued::setup() {
gwappa 4:fcf597f82632 97 LOGSTATE(Cued)
gwappa 4:fcf597f82632 98
gwappa 11:897ecd5413e0 99 trial.markEndOfWait();
gwappa 7:6744ec9ccc25 100
gwappa 19:50663f8815b8 101 if (task.mode.value != Report) {
gwappa 19:50663f8815b8 102 trial.flag.cued = true;
gwappa 19:50663f8815b8 103 }
gwappa 15:20f7f737c256 104
gwappa 17:0b241aa1f5b6 105 // configure lick handler
gwappa 16:33c17c62840e 106 if (task.mode.value != MotionAlt) {
gwappa 17:0b241aa1f5b6 107 // licking without a visual "go-cue" will be considered a "catch" response
gwappa 17:0b241aa1f5b6 108 events::lickhandler = &automaton::jump<Cued,WithResp>;
gwappa 17:0b241aa1f5b6 109 } else {
gwappa 17:0b241aa1f5b6 110 // for MotionAlt
gwappa 16:33c17c62840e 111 }
gwappa 11:897ecd5413e0 112
gwappa 17:0b241aa1f5b6 113 // configure whisk handler
gwappa 17:0b241aa1f5b6 114 // matters only for Motion & MotionAlt conditions
gwappa 16:33c17c62840e 115 switch (task.mode.value) {
gwappa 16:33c17c62840e 116 case Motion:
gwappa 12:06ea96546af1 117 events::whiskhandler = &Cued::gate;
gwappa 16:33c17c62840e 118 break;
gwappa 16:33c17c62840e 119 case MotionAlt:
gwappa 16:33c17c62840e 120 events::whiskhandler = &automaton::jump<Cued,WithResp>;
gwappa 16:33c17c62840e 121 break;
gwappa 16:33c17c62840e 122 default:
gwappa 17:0b241aa1f5b6 123 // do nothing
gwappa 17:0b241aa1f5b6 124 break;
gwappa 17:0b241aa1f5b6 125 }
gwappa 17:0b241aa1f5b6 126
gwappa 17:0b241aa1f5b6 127 // configure gate handler
gwappa 17:0b241aa1f5b6 128 // "gating" comes from the visual cue for Report & Associate
gwappa 17:0b241aa1f5b6 129 // from the whisking for Motion
gwappa 17:0b241aa1f5b6 130 if (task.mode.value != MotionAlt) {
gwappa 17:0b241aa1f5b6 131 events::gatehandler = &Cued::gate;
gwappa 17:0b241aa1f5b6 132 }
gwappa 17:0b241aa1f5b6 133
gwappa 17:0b241aa1f5b6 134 switch (task.mode.value) {
gwappa 17:0b241aa1f5b6 135 case Report:
gwappa 17:0b241aa1f5b6 136 case Associate:
gwappa 17:0b241aa1f5b6 137 visualOut.attachTurnOnCallback(&events::gate);
gwappa 17:0b241aa1f5b6 138 break;
gwappa 17:0b241aa1f5b6 139 case Motion:
gwappa 17:0b241aa1f5b6 140 events::whiskhandler = &events::gate;
gwappa 17:0b241aa1f5b6 141 break;
gwappa 17:0b241aa1f5b6 142 case MotionAlt:
gwappa 17:0b241aa1f5b6 143 events::whiskhandler = &automaton::jump<Cued,WithResp>;
gwappa 17:0b241aa1f5b6 144 break;
gwappa 7:6744ec9ccc25 145 }
gwappa 7:6744ec9ccc25 146
gwappa 7:6744ec9ccc25 147 // start cue output
gwappa 14:af3adf5d5ddf 148 switch(task.mode.value) {
gwappa 14:af3adf5d5ddf 149 case Report:
gwappa 15:20f7f737c256 150 visualOut.run();
gwappa 15:20f7f737c256 151 // no auditory cue
gwappa 15:20f7f737c256 152 break;
gwappa 14:af3adf5d5ddf 153 case Associate:
gwappa 14:af3adf5d5ddf 154 visualOut.run();
gwappa 15:20f7f737c256 155 // fallthrough (with auditory cue)
gwappa 14:af3adf5d5ddf 156 case Motion:
gwappa 16:33c17c62840e 157 case MotionAlt:
gwappa 11:897ecd5413e0 158 audioOut.write(1);
gwappa 11:897ecd5413e0 159 buzzerTicker.attach_us(&tickBuzzer, trial.aud_ticker_cycle);
gwappa 11:897ecd5413e0 160 }
gwappa 4:fcf597f82632 161
gwappa 4:fcf597f82632 162 // sets the timeout for the next state
gwappa 11:897ecd5413e0 163 stateTimeout.attach_us(&automaton::jump<Cued,NoResp>, ms_to_us(task.aud_dur_ms.value));
gwappa 4:fcf597f82632 164 }
gwappa 4:fcf597f82632 165
gwappa 7:6744ec9ccc25 166 void Cued::gate() {
gwappa 12:06ea96546af1 167 events::gatehandler = 0;
gwappa 12:06ea96546af1 168 events::whiskhandler = 0;
gwappa 19:50663f8815b8 169 trial.flag.cued = true;
gwappa 12:06ea96546af1 170 events::lickhandler = &automaton::jump<Cued,WithResp>;
gwappa 7:6744ec9ccc25 171 }
gwappa 7:6744ec9ccc25 172
gwappa 4:fcf597f82632 173 void Cued::teardown() {
gwappa 12:06ea96546af1 174 events::whiskhandler = 0;
gwappa 12:06ea96546af1 175 events::lickhandler = 0;
gwappa 12:06ea96546af1 176 events::gatehandler = 0;
gwappa 7:6744ec9ccc25 177 // end cue output
gwappa 11:897ecd5413e0 178 buzzerTicker.detach();
gwappa 11:897ecd5413e0 179 audioOut.write(0);
gwappa 16:33c17c62840e 180 if ((task.mode.value != Motion) && (task.mode.value != MotionAlt)) {
gwappa 12:06ea96546af1 181 visualOut.stop();
gwappa 7:6744ec9ccc25 182 }
gwappa 7:6744ec9ccc25 183 }
gwappa 7:6744ec9ccc25 184
gwappa 7:6744ec9ccc25 185 void Abort::setup() {
gwappa 7:6744ec9ccc25 186 LOGSTATE(Abort)
gwappa 14:af3adf5d5ddf 187 events::whiskhandler = 0;
gwappa 14:af3adf5d5ddf 188 events::lickhandler = 0;
gwappa 14:af3adf5d5ddf 189 events::gatehandler = 0;
gwappa 11:897ecd5413e0 190 trial.markEndOfWait();
gwappa 19:50663f8815b8 191 trial.flag.reset = true;
gwappa 8:973dcd190672 192 stateTimeout.attach_us(&automaton::done<Abort>, ms_to_us(task.post_dur_ms.value));
gwappa 7:6744ec9ccc25 193 }
gwappa 7:6744ec9ccc25 194
gwappa 7:6744ec9ccc25 195 void Abort::teardown() {
gwappa 7:6744ec9ccc25 196 finalize();
gwappa 4:fcf597f82632 197 }
gwappa 4:fcf597f82632 198
gwappa 4:fcf597f82632 199 void WithResp::setup() {
gwappa 4:fcf597f82632 200 LOGSTATE(WithResp)
gwappa 4:fcf597f82632 201
gwappa 19:50663f8815b8 202 trial.flag.responded = true;
gwappa 14:af3adf5d5ddf 203 events::whiskhandler = 0;
gwappa 14:af3adf5d5ddf 204 events::lickhandler = 0;
gwappa 14:af3adf5d5ddf 205 events::gatehandler = 0;
gwappa 4:fcf597f82632 206
gwappa 17:0b241aa1f5b6 207 if ((task.mode.value != Pair) && ((trial.response &= TrialFlags::Cues)!= 0)) {
gwappa 17:0b241aa1f5b6 208 // open/close the valve, only when the cue was there
gwappa 11:897ecd5413e0 209 rewardOut.start();
gwappa 9:e136394bdb39 210 }
gwappa 4:fcf597f82632 211
gwappa 5:849446d19406 212 stateTimeout.attach_us(&automaton::done<WithResp>, ms_to_us(task.post_dur_ms.value));
gwappa 4:fcf597f82632 213 }
gwappa 4:fcf597f82632 214
gwappa 4:fcf597f82632 215 void WithResp::teardown() {
gwappa 4:fcf597f82632 216 finalize();
gwappa 4:fcf597f82632 217 }
gwappa 4:fcf597f82632 218
gwappa 4:fcf597f82632 219 void NoResp::setup() {
gwappa 4:fcf597f82632 220 LOGSTATE(NoResp)
gwappa 14:af3adf5d5ddf 221 events::whiskhandler = 0;
gwappa 14:af3adf5d5ddf 222 events::lickhandler = 0;
gwappa 14:af3adf5d5ddf 223 events::gatehandler = 0;
gwappa 4:fcf597f82632 224
gwappa 11:897ecd5413e0 225 // no reward here no matter the mode
gwappa 7:6744ec9ccc25 226
gwappa 5:849446d19406 227 stateTimeout.attach_us(&automaton::done<NoResp>, ms_to_us(task.post_dur_ms.value));
gwappa 4:fcf597f82632 228 }
gwappa 4:fcf597f82632 229 void NoResp::teardown() {
gwappa 4:fcf597f82632 230 finalize();
gwappa 8:973dcd190672 231 }
gwappa 8:973dcd190672 232
gwappa 8:973dcd190672 233 void TestReward::setup() {
gwappa 8:973dcd190672 234 LOGSTATE(TestReward)
gwappa 8:973dcd190672 235
gwappa 8:973dcd190672 236 // open/close the valve
gwappa 16:33c17c62840e 237 rewardOut.setOnset(0);
gwappa 16:33c17c62840e 238 rewardOut.setDuration(ms_to_us(task.reward_dur_ms.value));
gwappa 11:897ecd5413e0 239 rewardOut.start();
gwappa 16:33c17c62840e 240 stateTimeout.attach_us(&automaton::done<TestReward>, ms_to_us(task.reward_dur_ms.value+100));
gwappa 8:973dcd190672 241 }
gwappa 8:973dcd190672 242
gwappa 8:973dcd190672 243 void TestReward::teardown() {
gwappa 8:973dcd190672 244 // do nothing
gwappa 4:fcf597f82632 245 }