Keisuke Sehara
/
STM32_Whisking
fast-feedback virtual target task code on STM Nucleo
states.cpp
- Committer:
- gwappa
- Date:
- 2018-12-13
- Revision:
- 32:1416e015016c
- Parent:
- 31:b320ca61a8c0
File content as of revision 32:1416e015016c:
#include "states.h" #include "rig.h" #include "automaton.h" #include "scheduler.h" #include "IO.h" #define STATE_IS_LOGGED #ifdef STATE_IS_LOGGED #define LOGSTATE(S) IO::info(#S); #else #define LOGSTATE(S) #endif void finalize() { trial.markTrialEnd(task); scheduler::reset(); } void Delay::setup() { LOGSTATE(Delay) // initialize the trial-related params trial.reset(task); // set up the timeout for the next state switch (task.mode.value) { case MotionAlt: scheduler::set(ms_to_us(trial.delay_dur_ms + task.prep_dur_ms.value), &automaton::jump<Delay,Staged>); break; default: if (task.prep_dur_ms.value > 0) { scheduler::set(ms_to_us(trial.delay_dur_ms), &automaton::jump<Delay,Prepare>); } else { switch (task.mode.value) { case Pair: scheduler::set(ms_to_us(trial.delay_dur_ms), &automaton::jump<Delay,Paired>); break; case Report: scheduler::set(ms_to_us(trial.delay_dur_ms), &automaton::jump<Delay,Cued>); break; case Stage: case Associate: case Motion: scheduler::set(ms_to_us(trial.delay_dur_ms), &automaton::jump<Delay,Staged>); } } } trial.markTrialStart(); } void Delay::teardown() { // do nothing } void Prepare::setup() { // mostly the same with for Delay // except that the animal cannot lick freely LOGSTATE(Prepare) // configure the interrupts lickIn.attach(&automaton::jump<Prepare,Abort>); // set timeout for the next state switch (task.mode.value) { case Pair: scheduler::set(ms_to_us(task.prep_dur_ms.value), &automaton::jump<Prepare,Paired>); break; case Report: scheduler::set(ms_to_us(task.prep_dur_ms.value), &automaton::jump<Prepare,Cued>); break; case Stage: case Associate: case Motion: scheduler::set(ms_to_us(task.prep_dur_ms.value), &automaton::jump<Delay,Staged>); } } void Prepare::teardown() { // de-register lick inhibition lickIn.detach(); } void Staged::setup() { LOGSTATE(Staged) trial.markEndOfWait(); audioOut.attachTurnOffCallback(&automaton::jump<Staged,NoResp>); audioOut.run(); switch (task.mode.value) { case Stage: // no punishment in response to lick if (visualOut.isEnabled()) { lickIn.detach(); // if any // silently goes to the paired state visualOut.attachTurnOnCallback(&automaton::jump<Staged,Paired>); } else { lickIn.attach(&Staged::logCatch); } break; case MotionAlt: // no punishment in response to lick // silently goes to the rewarded state trial.flag.cued = true; gateIn.attach(&automaton::jump<Staged,WithResp>); break; case Associate: lickIn.attach(&automaton::jump<Staged,WithResp>); // catch trial visualOut.attachTurnOnCallback(&automaton::jump<Staged,Cued>); break; case Motion: lickIn.attach(&automaton::jump<Staged,WithResp>); // catch trial gateIn.attach(&automaton::jump<Staged,Cued>); } switch (task.mode.value) { case Motion: case MotionAlt: break; case Stage: case Associate: default: visualOut.run(); // should run with an appropriate delay // and activates gateIn later } } void Staged::logCatch() { trial.flag.responded = true; } void Staged::teardown() { gateIn.detach(); lickIn.detach(); // if any audioOut.detachTurnOffCallback(); // in case the next state fails to do so } void Paired::setup() { LOGSTATE(Paired) if (task.mode.value == Pair) { trial.markEndOfWait(); visualOut.run(); } trial.flag.cued = true; visualOut.attachTurnOffCallback(&automaton::jump<Paired,Monitored>); lickIn.attach(&automaton::jump<Paired,Hit>); } void Paired::teardown() { visualOut.detachTurnOffCallback(); // if any lickIn.detach(); // if any } void Hit::setup() { LOGSTATE(Hit) trial.flag.rewarded = false; // force "test" trial mode scheduler::set(ms_to_us(1), &automaton::jump<Hit,WithResp>); } void Hit::teardown() { // do nothing } void Cued::setup() { LOGSTATE(Cued) if (task.mode.value == Report) { trial.markEndOfWait(); scheduler::set(ms_to_us(task.vis_dur_ms.value + task.resp_dur_ms.value), &automaton::jump<Cued,NoResp>); } scheduler::set(ms_to_us(task.vis_dur_ms.value + task.resp_dur_ms.value), &automaton::jump<Cued,NoResp>); trial.flag.cued = true; lickIn.attach(&automaton::jump<Cued,WithResp>); } void Cued::teardown() { lickIn.detach(); // end cue output switch (task.mode.value) { case Report: case Associate: visualOut.stop(); } switch (task.mode.value) { case Stage: case Associate: case Motion: case MotionAlt: audioOut.stop(); } } void Abort::setup() { LOGSTATE(Abort) audioOut.stop(); // if any visualOut.stop(); // if any trial.markEndOfWait(); trial.flag.reset = true; scheduler::set(ms_to_us(task.post_dur_ms.value), &automaton::done<Abort>); } void Abort::teardown() { finalize(); } void Monitored::setup() { LOGSTATE(Monitored) if (trial.flag.rewarded == true) { rewardOut.run(); } lickIn.attach(&automaton::jump<Monitored,WithResp>); scheduler::set(ms_to_us(task.resp_dur_ms.value), &automaton::jump<Monitored,NoResp>); } void Monitored::teardown() { audioOut.stop(); // if any lickIn.detach(); rewardOut.wait(); } void WithResp::setup() { LOGSTATE(WithResp) trial.flag.responded = true; audioOut.stop(); // if any (for Stage/MotionAlt) visualOut.stop(); // if any switch (task.mode.value) { case Pair: case Stage: if (!trial.flag.rewarded) { rewardOut.start(); } break; case Report: case Associate: case Motion: case MotionAlt: if (trial.flag.cued) { rewardOut.start(); } } scheduler::set(ms_to_us(task.post_dur_ms.value), &automaton::done<WithResp>); } void WithResp::teardown() { finalize(); } void NoResp::setup() { LOGSTATE(NoResp) scheduler::set(ms_to_us(task.post_dur_ms.value), &automaton::done<NoResp>); } void NoResp::teardown() { finalize(); } void TestReward::setup() { LOGSTATE(TestReward) // open/close the valve rewardOut.setOnset(0); rewardOut.setDuration(ms_to_us(task.reward_dur_ms.value)); rewardOut.start(); scheduler::set(ms_to_us(task.reward_dur_ms.value+100), &automaton::done<TestReward>); } void TestReward::teardown() { // do nothing } void ClearTrialIndex::setup() { trial.index = 1; scheduler::set(ms_to_us(10), &automaton::done<ClearTrialIndex>); } void ClearTrialIndex::teardown() { // do nothing }