Balazs Racz / Mbed 2 deprecated LedStrip_test

Dependencies:   mbed

Committer:
bracz
Date:
Sun Sep 22 15:03:22 2013 +0000
Revision:
11:b12ce020d1ba
Parent:
10:01eb82c2a01b
Parent:
9:c3d4c7059979
Child:
13:db79286e7ce6
merges cycle color;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bracz 0:109a7a5e3e6e 1 #include <queue>
juliogerchman 3:42efa00ffef4 2 #include <algorithm>
bracz 9:c3d4c7059979 3 #include <string>
bracz 0:109a7a5e3e6e 4
bracz 0:109a7a5e3e6e 5 #include "mbed.h"
bracz 0:109a7a5e3e6e 6
bracz 0:109a7a5e3e6e 7 DigitalOut myled(LED1);
bracz 4:5a2af711d510 8 DigitalOut led2(LED2);
bracz 0:109a7a5e3e6e 9
bracz 0:109a7a5e3e6e 10 Serial pc(USBTX, USBRX);
bracz 0:109a7a5e3e6e 11
bracz 0:109a7a5e3e6e 12 SPI spi(p5, p6, p20); // mosi, miso, sclk
bracz 0:109a7a5e3e6e 13 DigitalOut latch(p16);
bracz 0:109a7a5e3e6e 14 DigitalOut strobe(p17);
bracz 0:109a7a5e3e6e 15
juliogerchman 2:590e99f4a313 16 Ticker g_ticker;
juliogerchman 2:590e99f4a313 17
juliogerchman 2:590e99f4a313 18
bracz 1:1a0d5a780e57 19 #define LENGTH 160
bracz 1:1a0d5a780e57 20
bracz 0:109a7a5e3e6e 21 uint8_t strip[160];
bracz 0:109a7a5e3e6e 22
bracz 0:109a7a5e3e6e 23 #define BLACK 0x80
bracz 0:109a7a5e3e6e 24 #define BLUE (BLACK | 0x10)
bracz 0:109a7a5e3e6e 25 #define RED (BLACK | 0x04)
bracz 0:109a7a5e3e6e 26 #define GREEN (BLACK | 0x01)
bracz 0:109a7a5e3e6e 27 #define YELLOW (RED | GREEN)
bracz 0:109a7a5e3e6e 28 #define CYAN (GREEN | BLUE)
bracz 0:109a7a5e3e6e 29 #define MAGENTA (RED | BLUE)
bracz 0:109a7a5e3e6e 30 #define WHITE (RED | GREEN | BLUE)
bracz 0:109a7a5e3e6e 31
juliogerchman 2:590e99f4a313 32 #define FAST 0x40
juliogerchman 2:590e99f4a313 33
bracz 0:109a7a5e3e6e 34 uint8_t fade_result[] =
bracz 4:5a2af711d510 35 {0, 2, 3, 1};
bracz 4:5a2af711d510 36
bracz 0:109a7a5e3e6e 37
bracz 4:5a2af711d510 38 uint8_t google_colors[] = {BLUE, RED, YELLOW, BLUE, GREEN, RED};
bracz 4:5a2af711d510 39
bracz 4:5a2af711d510 40 uint8_t getbit(uint8_t from, uint8_t to)
bracz 4:5a2af711d510 41 {
bracz 0:109a7a5e3e6e 42 return fade_result[((from&1) << 1) | (to & 1)];
bracz 0:109a7a5e3e6e 43 }
bracz 0:109a7a5e3e6e 44
bracz 4:5a2af711d510 45 uint8_t getcolor(uint8_t from, uint8_t to)
bracz 4:5a2af711d510 46 {
bracz 0:109a7a5e3e6e 47 uint8_t result = 0x80;
bracz 0:109a7a5e3e6e 48 result |= getbit(from >> 0, to >> 0) << 0;
bracz 0:109a7a5e3e6e 49 result |= getbit(from >> 2, to >> 2) << 2;
bracz 0:109a7a5e3e6e 50 result |= getbit(from >> 4, to >> 4) << 4;
bracz 0:109a7a5e3e6e 51 return result;
bracz 0:109a7a5e3e6e 52 }
bracz 0:109a7a5e3e6e 53
bracz 0:109a7a5e3e6e 54
bracz 4:5a2af711d510 55 void write_strip(uint8_t* data, int len)
bracz 4:5a2af711d510 56 {
bracz 0:109a7a5e3e6e 57 latch = 0;
bracz 0:109a7a5e3e6e 58 for (int i = len - 1; i >= 0; i--) {
bracz 0:109a7a5e3e6e 59 spi.write(data[i]);
bracz 0:109a7a5e3e6e 60 }
bracz 0:109a7a5e3e6e 61 latch = 1;
bracz 0:109a7a5e3e6e 62 wait_us(2);
bracz 0:109a7a5e3e6e 63 latch = 0;
bracz 0:109a7a5e3e6e 64 }
bracz 0:109a7a5e3e6e 65
bracz 4:5a2af711d510 66 class Schedulable
bracz 4:5a2af711d510 67 {
bracz 0:109a7a5e3e6e 68 public:
bracz 0:109a7a5e3e6e 69 int time_;
bracz 0:109a7a5e3e6e 70 virtual void Run() = 0;
bracz 4:5a2af711d510 71
bracz 0:109a7a5e3e6e 72 bool operator<(const Schedulable& o) const {
bracz 0:109a7a5e3e6e 73 return time_ < o.time_;
bracz 0:109a7a5e3e6e 74 }
bracz 0:109a7a5e3e6e 75 };
bracz 0:109a7a5e3e6e 76
bracz 0:109a7a5e3e6e 77
bracz 0:109a7a5e3e6e 78 struct comp {
bracz 0:109a7a5e3e6e 79 bool operator()(const Schedulable* a, const Schedulable* b) {
bracz 0:109a7a5e3e6e 80 return *b < *a;
bracz 0:109a7a5e3e6e 81 }
bracz 0:109a7a5e3e6e 82 };
bracz 0:109a7a5e3e6e 83
bracz 0:109a7a5e3e6e 84 priority_queue<Schedulable*, vector<Schedulable*>, comp> task_list;
bracz 0:109a7a5e3e6e 85
bracz 4:5a2af711d510 86 void Schedule(Schedulable* action)
bracz 4:5a2af711d510 87 {
bracz 0:109a7a5e3e6e 88 task_list.push(action);
bracz 0:109a7a5e3e6e 89 }
bracz 0:109a7a5e3e6e 90
bracz 0:109a7a5e3e6e 91 int global_tick = 0;
bracz 0:109a7a5e3e6e 92 bool strip_changed;
bracz 0:109a7a5e3e6e 93
bracz 4:5a2af711d510 94 void tick_cb()
bracz 4:5a2af711d510 95 {
bracz 0:109a7a5e3e6e 96 ++global_tick;
bracz 0:109a7a5e3e6e 97 strobe = !strobe;
bracz 0:109a7a5e3e6e 98 }
bracz 0:109a7a5e3e6e 99
bracz 4:5a2af711d510 100 class RepeatedFadeInOut : public Schedulable
bracz 4:5a2af711d510 101 {
bracz 0:109a7a5e3e6e 102 public:
bracz 0:109a7a5e3e6e 103 RepeatedFadeInOut(int start_time, int led, uint8_t a, uint8_t b, bool fast)
bracz 0:109a7a5e3e6e 104 : led_(led), a_(a), b_(b), fast_(fast) {
bracz 0:109a7a5e3e6e 105 time_ = start_time;
bracz 0:109a7a5e3e6e 106 Schedule(this);
bracz 4:5a2af711d510 107 }
bracz 0:109a7a5e3e6e 108
bracz 0:109a7a5e3e6e 109 virtual void Run() {
bracz 4:5a2af711d510 110 strip[led_] = getcolor(a_, b_);
bracz 0:109a7a5e3e6e 111 if (fast_) {
juliogerchman 2:590e99f4a313 112 strip[led_] |= FAST;
bracz 0:109a7a5e3e6e 113 time_ += 128;
bracz 0:109a7a5e3e6e 114 } else {
bracz 0:109a7a5e3e6e 115 time_ += 256;
bracz 0:109a7a5e3e6e 116 }
bracz 0:109a7a5e3e6e 117 strip_changed = true;
bracz 0:109a7a5e3e6e 118 swap(a_,b_);
bracz 0:109a7a5e3e6e 119 Schedule(this);
bracz 0:109a7a5e3e6e 120 }
bracz 4:5a2af711d510 121
bracz 0:109a7a5e3e6e 122 private:
bracz 0:109a7a5e3e6e 123 int led_;
bracz 0:109a7a5e3e6e 124 uint8_t a_,b_;
bracz 0:109a7a5e3e6e 125 bool fast_;
bracz 0:109a7a5e3e6e 126 };
bracz 0:109a7a5e3e6e 127
bracz 4:5a2af711d510 128 class WalkingFadeInOut : public Schedulable
bracz 4:5a2af711d510 129 {
bracz 1:1a0d5a780e57 130 public:
bracz 1:1a0d5a780e57 131 WalkingFadeInOut(int start_time, int led, int stride, uint8_t a, uint8_t b, bool fast)
bracz 1:1a0d5a780e57 132 : led_(led - stride), stride_(stride), a_(a), b_(b), fast_(fast), step_(true) {
bracz 1:1a0d5a780e57 133 time_ = start_time;
bracz 1:1a0d5a780e57 134 Schedule(this);
bracz 4:5a2af711d510 135 }
bracz 1:1a0d5a780e57 136
bracz 1:1a0d5a780e57 137 virtual void Run() {
bracz 1:1a0d5a780e57 138 if (step_) {
bracz 1:1a0d5a780e57 139 step_ = false;
bracz 1:1a0d5a780e57 140 if (led_ >= 0) strip[led_] = a_;
bracz 1:1a0d5a780e57 141 led_ += stride_;
bracz 1:1a0d5a780e57 142 led_ %= LENGTH;
bracz 1:1a0d5a780e57 143 } else {
bracz 1:1a0d5a780e57 144 step_ = true;
bracz 1:1a0d5a780e57 145 }
bracz 4:5a2af711d510 146 strip[led_] = getcolor(a_, b_);
bracz 1:1a0d5a780e57 147 if (fast_) {
juliogerchman 2:590e99f4a313 148 strip[led_] |= FAST;
bracz 1:1a0d5a780e57 149 time_ += 128;
bracz 1:1a0d5a780e57 150 } else {
bracz 1:1a0d5a780e57 151 time_ += 256;
bracz 1:1a0d5a780e57 152 }
bracz 1:1a0d5a780e57 153 strip_changed = true;
bracz 1:1a0d5a780e57 154 swap(a_,b_);
bracz 1:1a0d5a780e57 155 Schedule(this);
bracz 1:1a0d5a780e57 156 }
bracz 4:5a2af711d510 157
bracz 1:1a0d5a780e57 158 private:
bracz 1:1a0d5a780e57 159 int led_, stride_;
bracz 1:1a0d5a780e57 160 uint8_t a_,b_;
bracz 1:1a0d5a780e57 161 bool fast_, step_;
bracz 4:5a2af711d510 162
bracz 1:1a0d5a780e57 163 };
bracz 1:1a0d5a780e57 164
bracz 4:5a2af711d510 165 class RegionWalkingFadeInOut : public Schedulable
bracz 4:5a2af711d510 166 {
juliogerchman 2:590e99f4a313 167 public:
juliogerchman 2:590e99f4a313 168 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)
juliogerchman 2:590e99f4a313 169 : 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) {
juliogerchman 2:590e99f4a313 170 time_ = start_time;
juliogerchman 2:590e99f4a313 171 Schedule(this);
bracz 4:5a2af711d510 172 }
bracz 1:1a0d5a780e57 173
juliogerchman 2:590e99f4a313 174 virtual void Run() {
juliogerchman 2:590e99f4a313 175 if (step_) {
juliogerchman 2:590e99f4a313 176 step_ = false;
juliogerchman 2:590e99f4a313 177 if (led_ >= 0) strip[led_ + start_led_] = a_;
juliogerchman 2:590e99f4a313 178 led_ += stride_;
juliogerchman 2:590e99f4a313 179 if (repeat_) {
juliogerchman 2:590e99f4a313 180 led_ %= length_;
juliogerchman 2:590e99f4a313 181 } else {
juliogerchman 3:42efa00ffef4 182 if (led_ >= length_) {
juliogerchman 3:42efa00ffef4 183 /*if (next_ && led_ == (length_ + stride_)) {
juliogerchman 2:590e99f4a313 184 next_->time_ = global_tick + 1;
juliogerchman 2:590e99f4a313 185 Schedule(next_);
juliogerchman 3:42efa00ffef4 186 }*/
juliogerchman 2:590e99f4a313 187 delete this;
juliogerchman 2:590e99f4a313 188 return;
juliogerchman 2:590e99f4a313 189 }
juliogerchman 2:590e99f4a313 190 }
juliogerchman 2:590e99f4a313 191 } else {
juliogerchman 3:42efa00ffef4 192 if (led_ == (length_ - 1) && drop_ && !repeat_) {
juliogerchman 2:590e99f4a313 193 if (next_) {
juliogerchman 3:42efa00ffef4 194 next_->time_ = global_tick + 257;
juliogerchman 2:590e99f4a313 195 Schedule(next_);
juliogerchman 2:590e99f4a313 196 }
juliogerchman 2:590e99f4a313 197 delete this;
juliogerchman 2:590e99f4a313 198 return;
juliogerchman 2:590e99f4a313 199 }
bracz 4:5a2af711d510 200 step_ = true;
juliogerchman 2:590e99f4a313 201 }
bracz 4:5a2af711d510 202 strip[led_ + start_led_] = getcolor(a_, b_);
juliogerchman 2:590e99f4a313 203 if (fast_) {
juliogerchman 2:590e99f4a313 204 strip[led_ + start_led_] |= FAST;
juliogerchman 2:590e99f4a313 205 time_ += 128;
juliogerchman 2:590e99f4a313 206 } else {
juliogerchman 2:590e99f4a313 207 time_ += 256;
juliogerchman 2:590e99f4a313 208 }
juliogerchman 2:590e99f4a313 209 strip_changed = true;
juliogerchman 2:590e99f4a313 210 swap(a_,b_);
juliogerchman 2:590e99f4a313 211 Schedule(this);
juliogerchman 2:590e99f4a313 212 }
bracz 4:5a2af711d510 213
juliogerchman 2:590e99f4a313 214 private:
juliogerchman 2:590e99f4a313 215 int led_, stride_;
juliogerchman 2:590e99f4a313 216 int start_led_, length_;
juliogerchman 2:590e99f4a313 217 uint8_t a_,b_;
juliogerchman 2:590e99f4a313 218 bool fast_, step_;
juliogerchman 2:590e99f4a313 219 bool repeat_, drop_;
juliogerchman 2:590e99f4a313 220 Schedulable* next_;
juliogerchman 2:590e99f4a313 221 };
juliogerchman 2:590e99f4a313 222
juliogerchman 8:77fd54b4864c 223 class WaitAndSetDone : public Schedulable {
juliogerchman 8:77fd54b4864c 224 public:
juliogerchman 8:77fd54b4864c 225 WaitAndSetDone(int start_time, bool* done)
juliogerchman 8:77fd54b4864c 226 : done_(done) {
juliogerchman 8:77fd54b4864c 227 time_ = start_time;
juliogerchman 8:77fd54b4864c 228 Schedule(this);
juliogerchman 8:77fd54b4864c 229 }
juliogerchman 8:77fd54b4864c 230
juliogerchman 8:77fd54b4864c 231 virtual void Run() {
juliogerchman 8:77fd54b4864c 232 strip_changed = true;
juliogerchman 8:77fd54b4864c 233 if (done_) *done_ = true;
juliogerchman 8:77fd54b4864c 234 delete this;
juliogerchman 8:77fd54b4864c 235 }
juliogerchman 8:77fd54b4864c 236
juliogerchman 8:77fd54b4864c 237 private:
juliogerchman 8:77fd54b4864c 238 bool* done_;
juliogerchman 8:77fd54b4864c 239 };
juliogerchman 8:77fd54b4864c 240
juliogerchman 7:e3b6f5741d9d 241 class FadeFillRegion : public Schedulable {
juliogerchman 7:e3b6f5741d9d 242 public:
juliogerchman 8:77fd54b4864c 243 FadeFillRegion(int start_time, int start_led, int length, uint8_t from_color, uint8_t to_color, bool fast, bool* done)
juliogerchman 8:77fd54b4864c 244 : start_led_(start_led), length_(length), from_color_(from_color), to_color_(to_color), fast_(fast), done_(done) {
juliogerchman 7:e3b6f5741d9d 245 time_ = start_time;
juliogerchman 7:e3b6f5741d9d 246 Schedule(this);
juliogerchman 7:e3b6f5741d9d 247 }
juliogerchman 7:e3b6f5741d9d 248
juliogerchman 7:e3b6f5741d9d 249 virtual void Run() {
juliogerchman 7:e3b6f5741d9d 250 for (int i = start_led_; i < start_led_ + length_; ++i) {
juliogerchman 7:e3b6f5741d9d 251 strip[i] = getcolor(from_color_, to_color_) | (fast_ ? FAST : 0);
juliogerchman 7:e3b6f5741d9d 252 }
juliogerchman 7:e3b6f5741d9d 253 strip_changed = true;
juliogerchman 8:77fd54b4864c 254 new WaitAndSetDone(global_tick + (fast_ ? 256 : 512), done_);
juliogerchman 7:e3b6f5741d9d 255 delete this;
juliogerchman 7:e3b6f5741d9d 256 }
juliogerchman 8:77fd54b4864c 257
juliogerchman 7:e3b6f5741d9d 258 private:
juliogerchman 7:e3b6f5741d9d 259 int start_led_, length_;
juliogerchman 7:e3b6f5741d9d 260 uint8_t from_color_, to_color_;
juliogerchman 7:e3b6f5741d9d 261 bool fast_;
juliogerchman 8:77fd54b4864c 262 bool* done_;
juliogerchman 7:e3b6f5741d9d 263 };
juliogerchman 7:e3b6f5741d9d 264
juliogerchman 2:590e99f4a313 265 /* Keep dropping water drops in a bucket, until it fills up. */
bracz 4:5a2af711d510 266 class DropBucketFill : public Schedulable
bracz 4:5a2af711d510 267 {
juliogerchman 2:590e99f4a313 268 public:
juliogerchman 8:77fd54b4864c 269 DropBucketFill(int start_time, int start_led, int length, int drop_size, uint8_t from_color, uint8_t to_color, int fade_out_pause, uint8_t fade_out_color, bool* done)
juliogerchman 8:77fd54b4864c 270 : start_led_(start_led), length_(length), original_length_(length), drop_size_(drop_size), from_color_(from_color), to_color_(to_color), fade_out_pause_(fade_out_pause), fade_out_color_(fade_out_color), done_(done) {
juliogerchman 2:590e99f4a313 271 time_ = start_time;
juliogerchman 2:590e99f4a313 272 Schedule(this);
juliogerchman 2:590e99f4a313 273 }
bracz 4:5a2af711d510 274
juliogerchman 2:590e99f4a313 275 virtual void Run() {
juliogerchman 2:590e99f4a313 276 // The bucket starts with a drop at its end.
juliogerchman 2:590e99f4a313 277 //strip[start_led_ + length_] = to_color_;
juliogerchman 2:590e99f4a313 278 //strip[start_led_ + length_] = RED;
juliogerchman 2:590e99f4a313 279 if (length_ > 0) {
juliogerchman 2:590e99f4a313 280 // There's still space in the bucket. Drop a new drop.
juliogerchman 3:42efa00ffef4 281 for (int i = 0; i < min(drop_size_, length_); ++i) {
juliogerchman 7:e3b6f5741d9d 282 Schedulable* next_drop = this;
juliogerchman 3:42efa00ffef4 283 new RegionWalkingFadeInOut(time_ + (256 * i / drop_size_), i, drop_size_, start_led_, length_, from_color_, to_color_, true, false, true, next_drop);
juliogerchman 2:590e99f4a313 284 }
juliogerchman 2:590e99f4a313 285 length_--;
bracz 4:5a2af711d510 286 } else if (length_ == 0) {
juliogerchman 2:590e99f4a313 287 // There's no more space in the bucket. Bail out.
juliogerchman 8:77fd54b4864c 288 new FadeFillRegion(global_tick + fade_out_pause_, start_led_, original_length_, to_color_, fade_out_color_, false, done_);
juliogerchman 2:590e99f4a313 289 delete this;
juliogerchman 2:590e99f4a313 290 return;
juliogerchman 2:590e99f4a313 291 }
juliogerchman 2:590e99f4a313 292 }
bracz 4:5a2af711d510 293
juliogerchman 2:590e99f4a313 294 private:
juliogerchman 7:e3b6f5741d9d 295 int start_led_, length_, original_length_;
juliogerchman 2:590e99f4a313 296 int drop_size_;
juliogerchman 2:590e99f4a313 297 uint8_t from_color_, to_color_;
juliogerchman 7:e3b6f5741d9d 298 int fade_out_pause_;
juliogerchman 7:e3b6f5741d9d 299 uint8_t fade_out_color_;
bracz 4:5a2af711d510 300 bool* done_;
juliogerchman 2:590e99f4a313 301 };
juliogerchman 2:590e99f4a313 302
bracz 4:5a2af711d510 303 Schedulable* g_watchdog;
bracz 4:5a2af711d510 304
bracz 4:5a2af711d510 305 class ProgramSupervisor
bracz 4:5a2af711d510 306 {
bracz 4:5a2af711d510 307 public:
juliogerchman 8:77fd54b4864c 308 ProgramSupervisor() {
juliogerchman 8:77fd54b4864c 309 next_program_ = 0;
juliogerchman 8:77fd54b4864c 310 }
bracz 4:5a2af711d510 311 // 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.
bracz 4:5a2af711d510 312 void RegisterProgram(Schedulable* program) {
bracz 4:5a2af711d510 313 programs_.push_back(program);
bracz 4:5a2af711d510 314 }
bracz 4:5a2af711d510 315
bracz 4:5a2af711d510 316 // This should be called by the program executor when it is completed.
bracz 4:5a2af711d510 317 // It is desired to leave all LEDs black after program completion.
bracz 4:5a2af711d510 318 void CurrentProgramDone() {
bracz 4:5a2af711d510 319 next_program_++;
bracz 4:5a2af711d510 320 next_program_ %= programs_.size();
bracz 4:5a2af711d510 321 ScheduleProgram();
bracz 4:5a2af711d510 322 }
bracz 4:5a2af711d510 323
bracz 4:5a2af711d510 324 void ScheduleProgram() {
bracz 4:5a2af711d510 325 global_tick = 0;
bracz 4:5a2af711d510 326 while (!task_list.empty()) task_list.pop();
bracz 4:5a2af711d510 327 Schedule(g_watchdog);
bracz 6:62c9a5483a84 328 memset(strip, 0x80, sizeof(strip));
bracz 6:62c9a5483a84 329 write_strip(strip, sizeof(strip));
bracz 4:5a2af711d510 330 if (programs_.empty()) return;
juliogerchman 8:77fd54b4864c 331 programs_[next_program_]->time_ = 0;
juliogerchman 8:77fd54b4864c 332 Schedule(programs_[next_program_]);
bracz 4:5a2af711d510 333 }
bracz 4:5a2af711d510 334
bracz 4:5a2af711d510 335
bracz 4:5a2af711d510 336 private:
bracz 4:5a2af711d510 337 vector<Schedulable*> programs_;
bracz 4:5a2af711d510 338 int next_program_; // indexes the programs_ array.
bracz 4:5a2af711d510 339 } supervisor;
bracz 4:5a2af711d510 340
bracz 4:5a2af711d510 341
bracz 4:5a2af711d510 342 class ProgramWatchdog : public Schedulable
bracz 4:5a2af711d510 343 {
bracz 4:5a2af711d510 344 public:
bracz 4:5a2af711d510 345 ProgramWatchdog() {
bracz 4:5a2af711d510 346 time_ = 5 * 60 * 1000; // 5 minutes deadline
bracz 4:5a2af711d510 347 }
bracz 4:5a2af711d510 348
bracz 4:5a2af711d510 349 virtual void Run() {
bracz 4:5a2af711d510 350 supervisor.CurrentProgramDone();
bracz 9:c3d4c7059979 351 if (this == g_watchdog) led2 = 1;
bracz 4:5a2af711d510 352 }
bracz 4:5a2af711d510 353
bracz 4:5a2af711d510 354 } g_watchdog_impl;
bracz 4:5a2af711d510 355
bracz 4:5a2af711d510 356
juliogerchman 10:01eb82c2a01b 357
juliogerchman 10:01eb82c2a01b 358 const int CycleColorsRegions[][2] = {
juliogerchman 10:01eb82c2a01b 359 {5, 10},
juliogerchman 10:01eb82c2a01b 360 {15, 10},
juliogerchman 10:01eb82c2a01b 361 {35, 5},
juliogerchman 10:01eb82c2a01b 362 {40, 50}
juliogerchman 10:01eb82c2a01b 363 };
juliogerchman 10:01eb82c2a01b 364
juliogerchman 10:01eb82c2a01b 365 class CycleColors : public Schedulable
juliogerchman 10:01eb82c2a01b 366 {
juliogerchman 10:01eb82c2a01b 367 public:
juliogerchman 10:01eb82c2a01b 368 CycleColors(bool fast, int cycle_count) : fast_(fast), cycle_count_(cycle_count), current_cycle_(0) {
juliogerchman 10:01eb82c2a01b 369 fade_out_time_ = fast_ ? 256 : 512;
juliogerchman 10:01eb82c2a01b 370 supervisor.RegisterProgram(this);
juliogerchman 10:01eb82c2a01b 371 }
juliogerchman 10:01eb82c2a01b 372
juliogerchman 10:01eb82c2a01b 373 virtual void Run() {
juliogerchman 10:01eb82c2a01b 374 strip[100] = RED;
juliogerchman 10:01eb82c2a01b 375 strip_changed = true;
juliogerchman 10:01eb82c2a01b 376
juliogerchman 10:01eb82c2a01b 377 int next_cycle_start_time = global_tick;
juliogerchman 10:01eb82c2a01b 378 for (int region = 0; region < sizeof(CycleColorsRegions) / sizeof(CycleColorsRegions[0]); ++region) {
juliogerchman 10:01eb82c2a01b 379 int region_start_led = CycleColorsRegions[region][0];
juliogerchman 10:01eb82c2a01b 380 int region_length = CycleColorsRegions[region][1];
juliogerchman 10:01eb82c2a01b 381 int region_from_color = google_colors[(current_cycle_ + region) % sizeof(google_colors)];
juliogerchman 10:01eb82c2a01b 382 int region_to_color = google_colors[(region_from_color + 1) % sizeof(google_colors)];
juliogerchman 10:01eb82c2a01b 383 new FadeFillRegion(next_cycle_start_time, region_start_led, region_length, region_from_color, region_to_color, fast_, NULL);
juliogerchman 10:01eb82c2a01b 384 }
juliogerchman 10:01eb82c2a01b 385
juliogerchman 10:01eb82c2a01b 386 ++current_cycle_;
juliogerchman 10:01eb82c2a01b 387 if (current_cycle_ < cycle_count_) {
juliogerchman 10:01eb82c2a01b 388 time_ += fade_out_time_;
juliogerchman 10:01eb82c2a01b 389 Schedule(this);
juliogerchman 10:01eb82c2a01b 390 } else {
juliogerchman 10:01eb82c2a01b 391 supervisor.CurrentProgramDone();
juliogerchman 10:01eb82c2a01b 392 }
juliogerchman 10:01eb82c2a01b 393 }
juliogerchman 10:01eb82c2a01b 394
juliogerchman 10:01eb82c2a01b 395 private:
juliogerchman 10:01eb82c2a01b 396 bool fast_;
juliogerchman 10:01eb82c2a01b 397 int fade_out_time_;
juliogerchman 10:01eb82c2a01b 398 int cycle_count_;
juliogerchman 10:01eb82c2a01b 399 int current_cycle_;
juliogerchman 10:01eb82c2a01b 400 };
juliogerchman 10:01eb82c2a01b 401
juliogerchman 10:01eb82c2a01b 402
bracz 4:5a2af711d510 403 class MultiDropBucketFillProgram : public Schedulable
bracz 4:5a2af711d510 404 {
bracz 4:5a2af711d510 405 public:
bracz 5:6f0f4e6c1e5f 406 MultiDropBucketFillProgram() {
bracz 5:6f0f4e6c1e5f 407 supervisor.RegisterProgram(this);
bracz 5:6f0f4e6c1e5f 408 }
bracz 5:6f0f4e6c1e5f 409
bracz 4:5a2af711d510 410 virtual void Run() {
bracz 4:5a2af711d510 411 int time = global_tick;
bracz 4:5a2af711d510 412 const int kLength = sizeof(google_colors);
bracz 4:5a2af711d510 413 memset(done_, 0, sizeof(done_));
bracz 4:5a2af711d510 414 for (int i = 0; i < kLength; i++) {
juliogerchman 8:77fd54b4864c 415 new DropBucketFill(time, 10 + i * 20, 20, 4, BLACK, google_colors[i], 2560, BLACK, done_ + i);
bracz 4:5a2af711d510 416 }
bracz 4:5a2af711d510 417 new EndWatcher(done_, kLength);
bracz 4:5a2af711d510 418 }
bracz 4:5a2af711d510 419
bracz 4:5a2af711d510 420 private:
bracz 4:5a2af711d510 421 class EndWatcher : public Schedulable {
bracz 4:5a2af711d510 422 public:
bracz 4:5a2af711d510 423 EndWatcher(bool* done_array, int len) : done_(done_array), len_(len) {
bracz 4:5a2af711d510 424 time_ = 0;
bracz 4:5a2af711d510 425 Schedule(this);
bracz 4:5a2af711d510 426 }
bracz 4:5a2af711d510 427
bracz 4:5a2af711d510 428 virtual void Run() {
bracz 4:5a2af711d510 429 int i;
bracz 4:5a2af711d510 430 for (i = 0; i < len_ && done_[i]; i++);
bracz 4:5a2af711d510 431 if (i < len_) {
bracz 4:5a2af711d510 432 // not done yet.
bracz 4:5a2af711d510 433 time_ = global_tick + 2;
bracz 4:5a2af711d510 434 Schedule(this);
bracz 4:5a2af711d510 435 } else {
bracz 4:5a2af711d510 436 supervisor.CurrentProgramDone();
bracz 4:5a2af711d510 437 delete this;
bracz 4:5a2af711d510 438 }
bracz 4:5a2af711d510 439 }
bracz 4:5a2af711d510 440
bracz 4:5a2af711d510 441 private:
bracz 4:5a2af711d510 442 bool* done_;
bracz 4:5a2af711d510 443 int len_;
bracz 4:5a2af711d510 444 };
bracz 4:5a2af711d510 445
bracz 4:5a2af711d510 446
bracz 4:5a2af711d510 447 bool done_[6];
bracz 4:5a2af711d510 448 };
bracz 4:5a2af711d510 449
bracz 9:c3d4c7059979 450 class WalkingFade : public Schedulable
bracz 9:c3d4c7059979 451 {
bracz 9:c3d4c7059979 452 public:
bracz 9:c3d4c7059979 453 WalkingFade(int start_time, int led, int stride, int end, uint8_t a, uint8_t b, bool fast)
bracz 9:c3d4c7059979 454 : led_(led), stride_(stride), end_(end), a_(a), b_(b), fast_(fast) {
bracz 9:c3d4c7059979 455 time_ = start_time;
bracz 9:c3d4c7059979 456 Schedule(this);
bracz 9:c3d4c7059979 457 }
bracz 9:c3d4c7059979 458
bracz 9:c3d4c7059979 459 virtual void Run() {
bracz 9:c3d4c7059979 460 if (led_ >= end_ || led_ < 0) {
bracz 9:c3d4c7059979 461 delete this;
bracz 9:c3d4c7059979 462 return;
bracz 9:c3d4c7059979 463 }
bracz 9:c3d4c7059979 464 strip[led_] = getcolor(a_, b_);
bracz 9:c3d4c7059979 465 led_ += stride_;
bracz 9:c3d4c7059979 466 if (fast_) {
bracz 9:c3d4c7059979 467 strip[led_] |= FAST;
bracz 9:c3d4c7059979 468 time_ += 128;
bracz 9:c3d4c7059979 469 } else {
bracz 9:c3d4c7059979 470 time_ += 256;
bracz 9:c3d4c7059979 471 }
bracz 9:c3d4c7059979 472 strip_changed = true;
bracz 9:c3d4c7059979 473 Schedule(this);
bracz 9:c3d4c7059979 474 }
bracz 9:c3d4c7059979 475
bracz 9:c3d4c7059979 476 private:
bracz 9:c3d4c7059979 477 int led_, stride_, end_;
bracz 9:c3d4c7059979 478 uint8_t a_,b_;
bracz 9:c3d4c7059979 479 bool fast_, step_;
bracz 9:c3d4c7059979 480 };
bracz 9:c3d4c7059979 481
bracz 9:c3d4c7059979 482
bracz 9:c3d4c7059979 483 class MorseGoogleProgram : public Schedulable {
bracz 9:c3d4c7059979 484 public:
bracz 9:c3d4c7059979 485 virtual void Run() {
bracz 9:c3d4c7059979 486 const string code = "W.... .- .--. .--. -.-- / -... .. .-. - .... -.. .- -.-- --..-- / B--. R--- Y--- B--. G.-.. R. ";
bracz 9:c3d4c7059979 487 const int kSpaceTime = 3*256;
bracz 9:c3d4c7059979 488 const int kLedStart = 150;
bracz 9:c3d4c7059979 489 const int kStride = -2;
bracz 9:c3d4c7059979 490 const int kHalfStrideTime = 64;
bracz 9:c3d4c7059979 491 const int kDotSpaceTime = 256;
bracz 9:c3d4c7059979 492 int time = global_tick;
bracz 9:c3d4c7059979 493 uint8_t color = WHITE;
bracz 9:c3d4c7059979 494 for (int i = 0; i < code.size(); i++) {
bracz 9:c3d4c7059979 495 switch (code[i]) {
bracz 9:c3d4c7059979 496 case 'R': color = RED ; break;
bracz 9:c3d4c7059979 497 case 'G': color = GREEN ; break;
bracz 9:c3d4c7059979 498 case 'B': color = BLUE ; break;
bracz 9:c3d4c7059979 499 case 'Y': color = YELLOW ; break;
bracz 9:c3d4c7059979 500 case 'W': color = WHITE ; break;
bracz 9:c3d4c7059979 501 case 'C': color = CYAN ; break;
bracz 9:c3d4c7059979 502 case 'M': color = MAGENTA ; break;
bracz 9:c3d4c7059979 503 case '.': {
bracz 9:c3d4c7059979 504 new WalkingFade(time, kLedStart, kStride, 160, BLACK, color, true); time += kHalfStrideTime;
bracz 9:c3d4c7059979 505 new WalkingFade(time, kLedStart - 1, kStride, 160, BLACK, color, true); time += kHalfStrideTime;
bracz 9:c3d4c7059979 506 new WalkingFade(time, kLedStart, kStride, 160, color, BLACK, true); time += kHalfStrideTime;
bracz 9:c3d4c7059979 507 new WalkingFade(time, kLedStart - 1, kStride, 160, color, BLACK, true); time += kHalfStrideTime;
bracz 9:c3d4c7059979 508 time += kDotSpaceTime;
bracz 9:c3d4c7059979 509 break;
bracz 9:c3d4c7059979 510 }
bracz 9:c3d4c7059979 511 case '-': {
bracz 9:c3d4c7059979 512 new WalkingFade(time, kLedStart, kStride, 160, BLACK, color, true); time += kHalfStrideTime;
bracz 9:c3d4c7059979 513 new WalkingFade(time, kLedStart - 1, kStride, 160, BLACK, color, true); time += kHalfStrideTime;
bracz 9:c3d4c7059979 514 time += 3 * kHalfStrideTime; // should create three complete pixels
bracz 9:c3d4c7059979 515 new WalkingFade(time, kLedStart, kStride, 160, color, BLACK, true); time += kHalfStrideTime;
bracz 9:c3d4c7059979 516 new WalkingFade(time, kLedStart - 1, kStride, 160, color, BLACK, true); time += kHalfStrideTime;
bracz 9:c3d4c7059979 517 time += kDotSpaceTime;
bracz 9:c3d4c7059979 518 break;
bracz 9:c3d4c7059979 519 }
bracz 9:c3d4c7059979 520 case '/': // fall-through
bracz 9:c3d4c7059979 521 case ' ': time += kSpaceTime; break;
bracz 9:c3d4c7059979 522 }
bracz 9:c3d4c7059979 523 }
bracz 9:c3d4c7059979 524 finaliser_.time_ = time + kLedStart * kHalfStrideTime + 2000;
bracz 9:c3d4c7059979 525 Schedule(&finaliser_);
bracz 9:c3d4c7059979 526 }
bracz 9:c3d4c7059979 527
bracz 9:c3d4c7059979 528 private:
bracz 9:c3d4c7059979 529 ProgramWatchdog finaliser_;
bracz 9:c3d4c7059979 530 };
bracz 9:c3d4c7059979 531
bracz 4:5a2af711d510 532
bracz 4:5a2af711d510 533 void init_board()
bracz 4:5a2af711d510 534 {
bracz 0:109a7a5e3e6e 535 pc.baud(115200);
bracz 0:109a7a5e3e6e 536
bracz 0:109a7a5e3e6e 537 myled = 0;
bracz 0:109a7a5e3e6e 538 latch = 0;
bracz 4:5a2af711d510 539
bracz 0:109a7a5e3e6e 540 spi.format(8, 0);
bracz 0:109a7a5e3e6e 541 spi.frequency(300000);
bracz 0:109a7a5e3e6e 542 wait_ms(500);
bracz 0:109a7a5e3e6e 543 myled = 1;
juliogerchman 2:590e99f4a313 544 memset(strip, BLACK, sizeof(strip));
bracz 0:109a7a5e3e6e 545 write_strip(strip, sizeof(strip));
juliogerchman 2:590e99f4a313 546 g_ticker.attach(&tick_cb, 1.0/1000);
bracz 4:5a2af711d510 547
bracz 0:109a7a5e3e6e 548 memset(strip, 0x0, sizeof(strip));
juliogerchman 2:590e99f4a313 549 }
juliogerchman 2:590e99f4a313 550
bracz 4:5a2af711d510 551 void run_loop()
bracz 4:5a2af711d510 552 {
bracz 0:109a7a5e3e6e 553 while(1) {
bracz 0:109a7a5e3e6e 554 while (task_list.empty() || global_tick < task_list.top()->time_) {
bracz 0:109a7a5e3e6e 555 if (strip_changed) {
bracz 0:109a7a5e3e6e 556 write_strip(strip, sizeof(strip));
bracz 0:109a7a5e3e6e 557 strip_changed = false;
bracz 0:109a7a5e3e6e 558 memset(strip, 0x0, sizeof(strip));
bracz 0:109a7a5e3e6e 559 }
bracz 0:109a7a5e3e6e 560 }
bracz 0:109a7a5e3e6e 561 Schedulable* action = task_list.top();
bracz 0:109a7a5e3e6e 562 task_list.pop();
bracz 0:109a7a5e3e6e 563 action->Run();
bracz 0:109a7a5e3e6e 564 }
juliogerchman 2:590e99f4a313 565 }
bracz 0:109a7a5e3e6e 566
bracz 4:5a2af711d510 567 int main()
bracz 4:5a2af711d510 568 {
juliogerchman 2:590e99f4a313 569 init_board();
bracz 4:5a2af711d510 570 g_watchdog = &g_watchdog_impl;
bracz 5:6f0f4e6c1e5f 571
juliogerchman 10:01eb82c2a01b 572 // MultiDropBucketFillProgram multi_drop;
bracz 11:b12ce020d1ba 573 //CycleColors cycle_colors(false, 5);
bracz 9:c3d4c7059979 574 MorseGoogleProgram morse;
bracz 5:6f0f4e6c1e5f 575
bracz 4:5a2af711d510 576 supervisor.ScheduleProgram();
juliogerchman 3:42efa00ffef4 577
juliogerchman 2:590e99f4a313 578 run_loop();
juliogerchman 2:590e99f4a313 579 }