Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 20:4c06d3041337, committed 2018-07-02
- 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
--- 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.
*/