fast-feedback virtual target task code on STM Nucleo

Dependencies:   mbed

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());
+    }
+}