Keisuke Sehara
/
STM32_Whisking
fast-feedback virtual target task code on STM Nucleo
Diff: main.cpp
- Revision:
- 0:f736749c33d2
- Child:
- 1:871d3066c2ab
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon May 14 14:12:32 2018 +0000 @@ -0,0 +1,172 @@ +#include "mbed.h" +#include "IO.h" +#include "random.h" + +/* + * command characters + */ +#define CMD_MODE_PAIR 'P' +#define CMD_MODE_APPEAR 'A' +#define CMD_TEST_REWARD 'T' +#define CMD_EXECUTE 'x' + +#define CHR_DELAY_MIN 'm' +#define CHR_DELAY_VAR 'v' +#define CHR_PREP_DUR 'p' +#define CHR_CUE_DUR 'c' +#define CHR_POST_DUR 'n' +#define CHR_REWARD_DUR 'r' + +#define STR_DELIMITER ";" +#define STR_NEWLINE "\r\n" + +Timeout interval; +DigitalOut cue(LED1); +InterruptIn whisking(USER_BUTTON); + +enum Mode { + Pair, + Appear +}; + +/** + * the trial mode. + */ +Mode mode = Pair; + +/** + * the minimum duration for the delay. + */ +uint16_t delay_min_ms = 3500; +/** + * the average for the (exponential) variable duration of the delay. + */ +uint16_t delay_var_ms = 3000; +/** + * the duration of the "preparatory period", during which licking is not allowed. + */ +uint16_t prep_dur_ms = 1500; +/** + * the cue duration. + */ +uint16_t cue_dur_ms = 3000; +/** + * the post-reward recording duration. + */ +uint16_t post_dur_ms = 4000; +/** + * the duration of reward, in microseconds + */ +unsigned long reward_us = 40000; + + +void writeModeToSerial(bool newline=true){ + IO::write(IO::CONFIG_HEADER); +#define WRITE(CHR, VAL) if (mode == (VAL)) { IO::write("[%c]",CHR); } else { IO::write("%c",CHR); } + WRITE(CMD_MODE_PAIR, Pair) + WRITE(CMD_MODE_APPEAR, Appear) +#undef WRITE + if (newline) { + IO::write(STR_NEWLINE); + } +} + +void writeSettingsToSerial() +{ + writeModeToSerial(false); + IO::write(STR_DELIMITER); +#define WRITE(CHR, PARAM, END) IO::write("%c%u",CHR,PARAM); if (END) { IO::write(STR_NEWLINE); } else { IO::write(STR_DELIMITER); } + WRITE(CHR_DELAY_MIN, delay_min_ms, false) + WRITE(CHR_DELAY_VAR, delay_var_ms, false) + WRITE(CHR_PREP_DUR, prep_dur_ms, false) + WRITE(CHR_CUE_DUR, cue_dur_ms, false) + WRITE(CHR_POST_DUR, post_dur_ms, false) + WRITE(CHR_REWARD_DUR, reward_us/1000, true) +#undef WRITE +} + +inline bool isWhitespace(const char& ch) { + return (ch == ' ') || + (ch == '\t') || + (ch == '\r') || + (ch == '\n') || + (ch == '\v') || + (ch == '\f'); +} + +uint16_t parseUnsignedFromSerial(const uint16_t& orig) +{ + uint16_t value = 0; + while(true) { + + int readChar = IO::getc(); + + // only accepts digits + if ((readChar >= 48) && (readChar <= 57)) { + value = value * 10 + (readChar - 48); + // continues parsing + + } else if ( isWhitespace((char)readChar) || (readChar == 59) ) { + // space or ';' + // ends parsing + break; + + } else { + IO::error("%c",(char)readChar); + // set value back to original + value = orig; + break; + + } + } + + return value; +} + +void parse(const char& in) { + if (isWhitespace(in)) { + return; + } + + switch(in) { + case CMD_TEST_REWARD: + // Cued::turnOnReward(); + // while(Cued::phase != Cued::Done); + // LOG_REWARDED + IO::result("done"); + break; + + case CMD_EXECUTE: + // TRIAL_STARTING + // automaton::run(); + IO::result("done"); + break; + + case '?': writeSettingsToSerial(); break; + case CMD_MODE_PAIR: mode = Pair; writeModeToSerial(); break; + case CMD_MODE_APPEAR: mode = Appear; writeModeToSerial(); break; +#define PARSE(CHR, TYPE, PARAM, FACTOR) case (CHR): PARAM = ((TYPE)(parseUnsignedFromSerial((uint16_t)((PARAM)/(FACTOR)))))*(FACTOR);\ + IO::config("%c%u",(CHR),((PARAM)/(FACTOR))); break; + + PARSE(CHR_DELAY_MIN, uint16_t, delay_min_ms, 1) + PARSE(CHR_DELAY_VAR, uint16_t, delay_var_ms, 1) + PARSE(CHR_PREP_DUR, uint16_t, prep_dur_ms, 1) + PARSE(CHR_CUE_DUR, uint16_t, cue_dur_ms, 1) + PARSE(CHR_POST_DUR, uint16_t, post_dur_ms, 1) + PARSE(CHR_REWARD_DUR, unsigned long, reward_us, 1000) +#undef PARSE + default: + IO::error("%c",in); + break; + } +} + +int main() +{ + // random::init(); + // automaton::init<Delay>(); + while(1){ + // wait for the host to access + parse(IO::getc()); + } +}