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.
Diff: main.cpp
- Revision:
- 4:5a2af711d510
- Parent:
- 3:42efa00ffef4
- Child:
- 5:6f0f4e6c1e5f
--- a/main.cpp Sat Sep 21 19:39:02 2013 +0000 +++ b/main.cpp Sat Sep 21 20:20:17 2013 +0000 @@ -4,6 +4,7 @@ #include "mbed.h" DigitalOut myled(LED1); +DigitalOut led2(LED2); Serial pc(USBTX, USBRX); @@ -30,13 +31,18 @@ #define FAST 0x40 uint8_t fade_result[] = - {0, 2, 3, 1}; +{0, 2, 3, 1}; + -uint8_t getbit(uint8_t from, uint8_t to) { +uint8_t google_colors[] = {BLUE, RED, YELLOW, BLUE, GREEN, RED}; + +uint8_t getbit(uint8_t from, uint8_t to) +{ return fade_result[((from&1) << 1) | (to & 1)]; } -uint8_t getcolor(uint8_t from, uint8_t to) { +uint8_t getcolor(uint8_t from, uint8_t to) +{ uint8_t result = 0x80; result |= getbit(from >> 0, to >> 0) << 0; result |= getbit(from >> 2, to >> 2) << 2; @@ -45,7 +51,8 @@ } -void write_strip(uint8_t* data, int len) { +void write_strip(uint8_t* data, int len) +{ latch = 0; for (int i = len - 1; i >= 0; i--) { spi.write(data[i]); @@ -55,11 +62,12 @@ latch = 0; } -class Schedulable { +class Schedulable +{ public: int time_; virtual void Run() = 0; - + bool operator<(const Schedulable& o) const { return time_ < o.time_; } @@ -74,28 +82,31 @@ priority_queue<Schedulable*, vector<Schedulable*>, comp> task_list; -void Schedule(Schedulable* action) { +void Schedule(Schedulable* action) +{ task_list.push(action); } int global_tick = 0; bool strip_changed; -void tick_cb() { +void tick_cb() +{ ++global_tick; strobe = !strobe; } -class RepeatedFadeInOut : public Schedulable { +class RepeatedFadeInOut : public Schedulable +{ public: RepeatedFadeInOut(int start_time, int led, uint8_t a, uint8_t b, bool fast) : led_(led), a_(a), b_(b), fast_(fast) { time_ = start_time; Schedule(this); - } + } virtual void Run() { - strip[led_] = getcolor(a_, b_); + strip[led_] = getcolor(a_, b_); if (fast_) { strip[led_] |= FAST; time_ += 128; @@ -106,20 +117,21 @@ swap(a_,b_); Schedule(this); } - + private: int led_; uint8_t a_,b_; bool fast_; }; -class WalkingFadeInOut : public Schedulable { +class WalkingFadeInOut : public Schedulable +{ public: WalkingFadeInOut(int start_time, int led, int stride, uint8_t a, uint8_t b, bool fast) : led_(led - stride), stride_(stride), a_(a), b_(b), fast_(fast), step_(true) { time_ = start_time; Schedule(this); - } + } virtual void Run() { if (step_) { @@ -130,7 +142,7 @@ } else { step_ = true; } - strip[led_] = getcolor(a_, b_); + strip[led_] = getcolor(a_, b_); if (fast_) { strip[led_] |= FAST; time_ += 128; @@ -141,21 +153,22 @@ swap(a_,b_); Schedule(this); } - + private: int led_, stride_; uint8_t a_,b_; bool fast_, step_; - + }; -class RegionWalkingFadeInOut : public Schedulable { +class RegionWalkingFadeInOut : public Schedulable +{ public: RegionWalkingFadeInOut(int start_time, int led, int stride, int start_led, int length, uint8_t a, uint8_t b, bool fast, bool repeat, bool drop, Schedulable* next) : led_(led - stride), stride_(stride), start_led_(start_led), length_(length), a_(a), b_(b), fast_(fast), step_(true), repeat_(repeat), drop_(drop), next_(next) { time_ = start_time; Schedule(this); - } + } virtual void Run() { if (step_) { @@ -183,9 +196,9 @@ delete this; return; } - step_ = true; + step_ = true; } - strip[led_ + start_led_] = getcolor(a_, b_); + strip[led_ + start_led_] = getcolor(a_, b_); if (fast_) { strip[led_ + start_led_] |= FAST; time_ += 128; @@ -196,7 +209,7 @@ swap(a_,b_); Schedule(this); } - + private: int led_, stride_; int start_led_, length_; @@ -207,14 +220,15 @@ }; /* Keep dropping water drops in a bucket, until it fills up. */ -class DropBucketFill : public Schedulable { +class DropBucketFill : public Schedulable +{ public: - DropBucketFill(int start_time, int start_led, int length, int drop_size, uint8_t from_color, uint8_t to_color) - : start_led_(start_led), length_(length), drop_size_(drop_size), from_color_(from_color), to_color_(to_color) { + DropBucketFill(int start_time, int start_led, int length, int drop_size, uint8_t from_color, uint8_t to_color, bool* done) + : start_led_(start_led), length_(length), drop_size_(drop_size), from_color_(from_color), to_color_(to_color), done_(done) { time_ = start_time; Schedule(this); } - + virtual void Run() { // The bucket starts with a drop at its end. //strip[start_led_ + length_] = to_color_; @@ -227,25 +241,120 @@ new RegionWalkingFadeInOut(time_ + (256 * i / drop_size_), i, drop_size_, start_led_, length_, from_color_, to_color_, true, false, true, next_drop); } length_--; - } else { + } else if (length_ == 0) { // There's no more space in the bucket. Bail out. + if (done_) *done_ = true; delete this; return; } } - + private: int start_led_, length_; int drop_size_; uint8_t from_color_, to_color_; + bool* done_; }; -void init_board() { +Schedulable* g_watchdog; + +class ProgramSupervisor +{ +public: + + // The program should be alive forever. Programs do not delete themselves upon completion. Every scheduling of a program happens with global time set to zero. + void RegisterProgram(Schedulable* program) { + programs_.push_back(program); + } + + // This should be called by the program executor when it is completed. + // It is desired to leave all LEDs black after program completion. + void CurrentProgramDone() { + next_program_++; + next_program_ %= programs_.size(); + ScheduleProgram(); + } + + void ScheduleProgram() { + global_tick = 0; + while (!task_list.empty()) task_list.pop(); + Schedule(g_watchdog); + if (programs_.empty()) return; + } + + +private: + vector<Schedulable*> programs_; + int next_program_; // indexes the programs_ array. +} supervisor; + + +class ProgramWatchdog : public Schedulable +{ +public: + ProgramWatchdog() { + time_ = 5 * 60 * 1000; // 5 minutes deadline + } + + virtual void Run() { + supervisor.CurrentProgramDone(); + led2 = 1; + } + +} g_watchdog_impl; + + +class MultiDropBucketFillProgram : public Schedulable +{ +public: + virtual void Run() { + int time = global_tick; + const int kLength = sizeof(google_colors); + memset(done_, 0, sizeof(done_)); + for (int i = 0; i < kLength; i++) { + new DropBucketFill(time, 10 + i * 20, 20, 4, BLACK, google_colors[i], done_ + i); + } + new EndWatcher(done_, kLength); + } + +private: + class EndWatcher : public Schedulable { + public: + EndWatcher(bool* done_array, int len) : done_(done_array), len_(len) { + time_ = 0; + Schedule(this); + } + + virtual void Run() { + int i; + for (i = 0; i < len_ && done_[i]; i++); + if (i < len_) { + // not done yet. + time_ = global_tick + 2; + Schedule(this); + } else { + supervisor.CurrentProgramDone(); + delete this; + } + } + + private: + bool* done_; + int len_; + }; + + + bool done_[6]; +}; + + +void init_board() +{ pc.baud(115200); myled = 0; latch = 0; - + spi.format(8, 0); spi.frequency(300000); wait_ms(500); @@ -253,11 +362,12 @@ memset(strip, BLACK, sizeof(strip)); write_strip(strip, sizeof(strip)); g_ticker.attach(&tick_cb, 1.0/1000); - + memset(strip, 0x0, sizeof(strip)); } -void run_loop() { +void run_loop() +{ while(1) { while (task_list.empty() || global_tick < task_list.top()->time_) { if (strip_changed) { @@ -272,19 +382,10 @@ } } -int main() { +int main() +{ init_board(); - - int stride = 7; - for (int i = 0; i < stride; i++) { - //new WalkingFadeInOut((256 * i / stride), i, stride, BLACK, RED, true); - /* new RepeatedFadeInOut(0, i, BLACK, RED, false); */ - //new RegionWalkingFadeInOut((256 * i / stride), i, stride, 5, 30, BLACK, BLUE, true, false); - } - - new DropBucketFill(0, 10, 20, 3, BLACK, BLUE); - - new DropBucketFill(0, 30, 20, 11, BLACK, GREEN); - + g_watchdog = &g_watchdog_impl; + supervisor.ScheduleProgram(); run_loop(); } \ No newline at end of file