Keisuke Sehara / Mbed 2 deprecated STM32_Whisking

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
gwappa
Date:
Mon Jul 02 09:04:45 2018 +0000
Parent:
19:50663f8815b8
Child:
21:e51733fc1c36
Commit message:
try extending Pulse to allow tickering output

Changed in this revision

pulse.cpp Show annotated file Show diff for this revision Revisions of this file
pulse.h Show annotated file Show diff for this revision Revisions of this file
rig.cpp Show annotated file Show diff for this revision Revisions of this file
rig.h Show annotated file Show diff for this revision Revisions of this file
states.cpp Show annotated file Show diff for this revision Revisions of this file
states.h Show annotated file Show diff for this revision Revisions of this file
task.cpp Show annotated file Show diff for this revision Revisions of this file
task.h Show annotated file Show diff for this revision Revisions of this file
trial.cpp Show annotated file Show diff for this revision Revisions of this file
trial.h Show annotated file Show diff for this revision Revisions of this file
--- a/pulse.cpp	Mon Jul 02 08:26:44 2018 +0000
+++ b/pulse.cpp	Mon Jul 02 09:04:45 2018 +0000
@@ -1,12 +1,16 @@
 #include "pulse.h"
 
-Pulse::Pulse(PinName pin, const uint64_t& onset_us, const uint64_t& duration_us):
+Pulse::Pulse(PinName pin,
+             const uint64_t& onset_us,
+             const uint64_t& duration_us,
+             const uint64_t& blink_us):
     out_(pin, 0),
     enabled_(true),
     stat_(Rest)
 {
     setOnset(onset_us);
     setDuration(duration_us);
+    setBlinkDuration(blink_us);
 }
 
 void Pulse::setEnabled(const bool& value)
@@ -29,6 +33,11 @@
     dur_ = value_us;
 }
 
+void Pulse::setBlinkDuration(const uint64_t& value_us)
+{
+    blinkdur_ = value_us;
+}
+
 void Pulse::attachTurnOnCallback(Callback<void ()> cb)
 {
     turnon_ = cb;
@@ -69,6 +78,9 @@
     stat_ = Active;
     out_.write(1);
     timer_.attach_us(callback(this, &Pulse::stop), dur_);
+    if (blinkdur_ > 0) {
+        blinker_.attach_us(callback(this, &Pulse::blink), blinkdur_);
+    }
     if (turnon_) {
         turnon_();
     }
@@ -79,6 +91,8 @@
     if (!enabled_) return;
     
     timer_.detach();
+    blinker_.detach();
+    
     out_.write(0);
     stat_ = Rest;
     if (turnoff_) {
@@ -86,6 +100,11 @@
     }
 }
 
+void Pulse::blink()
+{
+    out_ = !out_;
+}
+
 void Pulse::direct(const bool& value) {
     out_.write(value? 1:0);
 }
--- a/pulse.h	Mon Jul 02 08:26:44 2018 +0000
+++ b/pulse.h	Mon Jul 02 09:04:45 2018 +0000
@@ -28,11 +28,14 @@
         Rest
     };
 
-    Pulse(PinName pin, const uint64_t& onset_us=0, const uint64_t& duration_us=1000);
+    Pulse(PinName pin, const uint64_t& onset_us=0, const uint64_t& duration_us=1000, const uint64_t& blink_us=0);
+    
     void setEnabled(const bool& value);
     bool isEnabled();
     void setOnset(const uint64_t& value_us);
     void setDuration(const uint64_t& value_us);
+    void setBlinkDuration(const uint64_t& vaue_us);
+    
     void attachTurnOnCallback(Callback<void ()> cb=0);
     void attachTurnOffCallback(Callback<void ()> cb=0);
     void detachTurnOnCallback();
@@ -69,12 +72,15 @@
     void wait();
 
 private:
+    void blink();
 
     DigitalOut  out_;
     Timeout     timer_;
+    Ticker      blinker_;
     bool        enabled_;
     uint64_t    onset_;
     uint64_t    dur_;
+    uint64_t    blinkdur_;
     Callback<void ()> turnon_;
     Callback<void ()> turnoff_;
     
--- a/rig.cpp	Mon Jul 02 08:26:44 2018 +0000
+++ b/rig.cpp	Mon Jul 02 09:04:45 2018 +0000
@@ -20,15 +20,12 @@
 // trigger time out for TASK output
 Timeout      triggerTimeout;
 
-// ticker for audio cue
-Ticker       buzzerTicker;
-
 // input
 InterruptIn  whiskIn(ARDUINO_12);   // or USER_BUTTON
 InterruptIn  lickIn(ARDUINO_13);    // or USER_BUTTON
 
 // output
-DigitalOut   audioOut(ARDUINO_A0);    // or LED1
+Pulse        audioOut(ARDUINO_A0);    // or LED1
 Pulse        visualOut(ARDUINO_A1); // 
 Pulse        rewardOut(ARDUINO_A2); //
 
--- a/rig.h	Mon Jul 02 08:26:44 2018 +0000
+++ b/rig.h	Mon Jul 02 09:04:45 2018 +0000
@@ -27,7 +27,7 @@
 extern InterruptIn  lickIn;
 
 // output
-extern DigitalOut   audioOut;
+extern Pulse        audioOut;
 extern Pulse        visualOut;
 extern Pulse        rewardOut;
 
--- a/states.cpp	Mon Jul 02 08:26:44 2018 +0000
+++ b/states.cpp	Mon Jul 02 09:04:45 2018 +0000
@@ -12,12 +12,7 @@
 #define LOGSTATE(S)
 #endif
 
-void tickBuzzer() {
-    audioOut = !audioOut;
-}
-
 void finalize() {
-    audioOut.write(0); // if any
     trial.markTrialEnd();
 }
 
@@ -26,7 +21,6 @@
     
     // initialize the trial-related params
     trial.reset(task);
-    audioOut.write(0);
     events::setup(true);
     
     // set up the timeout for the next state
@@ -147,16 +141,11 @@
     // start cue output
     switch(task.mode.value) {
     case Report:
-        visualOut.run();
-        // no auditory cue
-        break;
     case Associate:
-        visualOut.run();
-        // fallthrough (with auditory cue)
     case Motion:
     case MotionAlt:
-        audioOut.write(1);
-        buzzerTicker.attach_us(&tickBuzzer, trial.aud_ticker_cycle);
+        visualOut.run();
+        audioOut.run();
     }
     
     // sets the timeout for the next state
@@ -174,12 +163,20 @@
     events::whiskhandler = 0;
     events::lickhandler  = 0;
     events::gatehandler  = 0;
+    
     // end cue output
-    buzzerTicker.detach();
-    audioOut.write(0);
-    if ((task.mode.value != Motion) && (task.mode.value != MotionAlt)) {
+    switch (task.mode.value) {
+    case Report:
+    case Associate:
         visualOut.stop();
     }
+    
+    switch (task.mode.value) {
+    case Associate:
+    case Motion:
+    case MotionAlt:
+        audioOut.stop();
+    }
 }
 
 void Abort::setup() {
@@ -204,7 +201,7 @@
     events::lickhandler  = 0;
     events::gatehandler  = 0;
     
-    if ((task.mode.value != Pair) && ((trial.response &= TrialFlags::Cues)!= 0)) {
+    if ((task.mode.value == Pair) || trial.flag.cued ) {
         // open/close the valve, only when the cue was there
         rewardOut.start();
     }
--- a/states.h	Mon Jul 02 08:26:44 2018 +0000
+++ b/states.h	Mon Jul 02 09:04:45 2018 +0000
@@ -36,6 +36,7 @@
 */
 struct Paired {
     static void setup();
+    static void gate();
     static void teardown();
 };
 
--- a/task.cpp	Mon Jul 02 08:26:44 2018 +0000
+++ b/task.cpp	Mon Jul 02 09:04:45 2018 +0000
@@ -12,11 +12,11 @@
     aud_tick_hz     (CFG_AUD_FREQ),
     resp_dur_ms     (CFG_RESP_DUR),
     post_dur_ms     (CFG_POST_DUR),
-    reward_on_ms    (CFG_REWARD_ONSET),
     reward_dur_ms   (CFG_REWARD_DUR),
     pre_min_ms      (CFG_PRE_MIN),
     vis_min_ms      (CFG_VIS_MIN),
     vis_avg_ms      (CFG_VIS_AVG),
+    vis_blink_hz    (CFG_VIS_FREQ),
     vis_fail_perc   (CFG_VIS_FAIL),
     test_reward     (CMD_TEST_REWARD, callback(this, &Task::testReward)),
     run             (CMD_EXECUTE,     callback(this, &Task::runTrial))
--- a/task.h	Mon Jul 02 08:26:44 2018 +0000
+++ b/task.h	Mon Jul 02 09:04:45 2018 +0000
@@ -18,11 +18,11 @@
 #define CFG_AUD_FREQ        'f', (4)
 #define CFG_RESP_DUR        'y', (2000)
 #define CFG_POST_DUR        'n', (4000)
-#define CFG_REWARD_ONSET    'u', (500)
 #define CFG_REWARD_DUR      'r', (40)
 #define CFG_PRE_MIN         'o', (1000)
 #define CFG_VIS_MIN         'j', (1)
 #define CFG_VIS_AVG         'v', (50)
+#define CFG_VIS_FREQ        'b', (4)
 #define CFG_VIS_FAIL        'q', (30)
 
 enum Mode {
@@ -76,8 +76,6 @@
     
     Property<uint16_t>  post_dur_ms;    // the post-reward recording duration.
     
-    Property<uint16_t>  reward_on_ms;   // the onset of reward relative to visual cue during Pair.
-    
     Property<uint16_t>  reward_dur_ms;  // the duration of reward.
     
     Property<uint16_t>  pre_min_ms;     // the minimum onset for the (passive) visual cue.
@@ -86,6 +84,8 @@
     
     Property<uint16_t>  vis_avg_ms;     // the average duration for the (passive) visual cue.
     
+    Property<uint16_t>  vis_blink_hz;   // the blinking frequency (any positive number), or disabled (0)
+    
     Property<uint16_t>  vis_fail_perc;     // the 'failure rate' of the (passive) visual cue.
     
     Action              test_reward;
--- a/trial.cpp	Mon Jul 02 08:26:44 2018 +0000
+++ b/trial.cpp	Mon Jul 02 09:04:45 2018 +0000
@@ -6,13 +6,17 @@
 
 const uint64_t MicrosecondsInSecond = 1000000;
 
-void TrialFlag::reset() {
+inline uint64_t calc_blink_duration(const uint16_t& freq) {
+    return (freq == 0)? 0 : (MicrosecondsInSecond/(freq * 2));
+}
+
+void TrialFlag::clear() {
     cued        = false;
     responded   = false;
     reset       = false;
 }
 
-void writeToSerial() {
+void TrialFlag::writeToSerial() {
     if (reset) {
         IO::write("reset");
     } else if (cued) {
@@ -24,27 +28,22 @@
 
 void Trial::reset(const Task& task){
     // reset score
-    flag.reset();
+    flag.clear();
     
     // set delay duration
     delay_dur_ms  = task.delay_min_ms.value
                     + random::exponential(task.delay_var_ms.value, task.delay_var_ms.value*3);
-    
-    aud_ticker_cycle = MicrosecondsInSecond/(task.aud_tick_hz.value * 2);
                     
-    // generate visual stimulus
+    // generate stimuli
+    audioOut.setEnabled(false);
     visualOut.setEnabled(false);
     vis_dur_us      = 0;
     vis_onset_us    = 0;
     
     switch (task.mode.value) {
     case Pair:
-        vis_onset_us    = ms_to_us(task.pre_min_ms.value);
-        vis_dur_us      = ms_to_us(task.vis_avg_ms.value);
-        visualOut.setEnabled(true);
-        visualOut.setOnset(vis_onset_us);
-        visualOut.setDuration(vis_dur_us);
-        rewardOut.setOnset(ms_to_us(task.reward_on_ms.value));
+        visualOut.setBlinkDuration( calc_blink_duration(task.vis_blink_hz.value) );
+        assignRandomStim(task);
         rewardOut.setDuration(ms_to_us(task.reward_dur_ms.value));
         break;
     case Report:
@@ -55,6 +54,12 @@
     case MotionAlt:
         rewardOut.setOnset(0);
         rewardOut.setDuration(ms_to_us(task.reward_dur_ms.value));
+        if (task.mode.value != Report) {
+            audioOut.setEnabled(true);
+            audioOut.setOnset(0);
+            audioOut.setDuration(ms_to_us(task.aud_dur_ms.value));
+            audioOut.setBlinkDuration( calc_blink_duration(task.aud_tick_hz.value) );
+        }
         break;
     }
     
@@ -72,17 +77,17 @@
     const uint32_t  mindur_us   = ms_to_us(task.vis_min_ms.value);
     const double    failure_perc = (task.vis_fail_perc.value > 0)? ((double)(task.vis_fail_perc.value)):1e-6;
     
-    const double    onsetvar    = (double)(phasedur_us - minonset_us - respdur_us - mindur_us);
-    const double    taudenom    = ::log(100.0) - ::log(failure_perc);
-    const double    ftau        = onsetvar/taudenom;
+    const double    onset_vrng  = (double)(phasedur_us - minonset_us - respdur_us - mindur_us);
+    const double    logdecay    = ::log(100.0) - ::log(failure_perc);
+    const double    ftau        = onset_vrng/logdecay;
     const uint32_t  tau         = (uint32_t)(ftau + 0.5);
-    const uint32_t  onset_us    = random::exponential(tau, onsetvar+10) + minonset_us;
-    const uint32_t  maxonset_us = onsetvar + minonset_us;
+    const uint32_t  onset_us    = random::exponential(tau, onset_vrng+10) + minonset_us;
+    const uint32_t  maxonset_us = onset_vrng + minonset_us;
     
-    if (onset_us < maxonset_us) {
+    if ((onset_us > 0) && (onset_us < maxonset_us)) {
         // generate duration
-        const uint32_t durvar   = maxonset_us - onset_us;
-        const uint32_t dur_us   = random::exponential(avgdur_us - mindur_us, durvar) + mindur_us;
+        const uint32_t dur_vrng = maxonset_us - onset_us;
+        const uint32_t dur_us   = random::exponential(avgdur_us - mindur_us, dur_vrng) + mindur_us;
         
         visualOut.setEnabled(true);
         visualOut.setDuration(dur_us);
@@ -90,11 +95,13 @@
         
         vis_dur_us      = dur_us;
         vis_onset_us    = onset_us;
+        IO::debug("visual(onset=%u,dur=%u)",vis_onset_us,vis_dur_us);
     } else {
         // no pulse
         visualOut.setEnabled(false);
         vis_dur_us      = 0;
         vis_onset_us    = 0;
+        IO::debug("visual(disabled)");
     }
 }
 
@@ -123,7 +130,7 @@
     
     IO::write(";wait%u", waiting);
     
-    if (visualOut.isEnabled() && (response != Responses::Reset)) {
+    if (visualOut.isEnabled() && (!flag.reset)) {
         IO::write(";visual(onset%u,duration%u)",vis_onset_us,vis_dur_us);
     }
     
--- a/trial.h	Mon Jul 02 08:26:44 2018 +0000
+++ b/trial.h	Mon Jul 02 09:04:45 2018 +0000
@@ -12,9 +12,9 @@
     bool responded;
     bool reset;
     
-    TrialFlag() cued(false), responded(false), reset(false) {}
+    TrialFlag(): cued(false), responded(false), reset(false) {}
     
-    void reset();
+    void clear();
     void writeToSerial();
 };
 
@@ -46,8 +46,6 @@
     uint16_t      vis_onset_us;
     uint16_t      vis_dur_us;
     
-    uint64_t      aud_ticker_cycle;
-    
     /**
     *   a buffer for recording licking events during the trial.
     */