Julio G / Mbed 2 deprecated LedStrip

Dependencies:   mbed

Fork of LedStrip_test by Balazs Racz

Revision:
5:5a2af711d510
Parent:
3:42efa00ffef4
Child:
6: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