Julio G / Mbed 2 deprecated LedStrip

Dependencies:   mbed

Fork of LedStrip_test by Balazs Racz

Committer:
juliogerchman
Date:
Sat Sep 21 20:28:03 2013 +0000
Revision:
4:e3b6f5741d9d
Parent:
3:42efa00ffef4
Child:
8:77fd54b4864c
Fade Out after bucket fill

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bracz 0:109a7a5e3e6e 1 #include <queue>
juliogerchman 3:42efa00ffef4 2 #include <algorithm>
bracz 0:109a7a5e3e6e 3
bracz 0:109a7a5e3e6e 4 #include "mbed.h"
bracz 0:109a7a5e3e6e 5
bracz 0:109a7a5e3e6e 6 DigitalOut myled(LED1);
bracz 0:109a7a5e3e6e 7
bracz 0:109a7a5e3e6e 8 Serial pc(USBTX, USBRX);
bracz 0:109a7a5e3e6e 9
bracz 0:109a7a5e3e6e 10 SPI spi(p5, p6, p20); // mosi, miso, sclk
bracz 0:109a7a5e3e6e 11 DigitalOut latch(p16);
bracz 0:109a7a5e3e6e 12 DigitalOut strobe(p17);
bracz 0:109a7a5e3e6e 13
juliogerchman 2:590e99f4a313 14 Ticker g_ticker;
juliogerchman 2:590e99f4a313 15
juliogerchman 2:590e99f4a313 16
bracz 1:1a0d5a780e57 17 #define LENGTH 160
bracz 1:1a0d5a780e57 18
bracz 0:109a7a5e3e6e 19 uint8_t strip[160];
bracz 0:109a7a5e3e6e 20
bracz 0:109a7a5e3e6e 21 #define BLACK 0x80
bracz 0:109a7a5e3e6e 22 #define BLUE (BLACK | 0x10)
bracz 0:109a7a5e3e6e 23 #define RED (BLACK | 0x04)
bracz 0:109a7a5e3e6e 24 #define GREEN (BLACK | 0x01)
bracz 0:109a7a5e3e6e 25 #define YELLOW (RED | GREEN)
bracz 0:109a7a5e3e6e 26 #define CYAN (GREEN | BLUE)
bracz 0:109a7a5e3e6e 27 #define MAGENTA (RED | BLUE)
bracz 0:109a7a5e3e6e 28 #define WHITE (RED | GREEN | BLUE)
bracz 0:109a7a5e3e6e 29
juliogerchman 2:590e99f4a313 30 #define FAST 0x40
juliogerchman 2:590e99f4a313 31
bracz 0:109a7a5e3e6e 32 uint8_t fade_result[] =
bracz 0:109a7a5e3e6e 33 {0, 2, 3, 1};
bracz 0:109a7a5e3e6e 34
bracz 0:109a7a5e3e6e 35 uint8_t getbit(uint8_t from, uint8_t to) {
bracz 0:109a7a5e3e6e 36 return fade_result[((from&1) << 1) | (to & 1)];
bracz 0:109a7a5e3e6e 37 }
bracz 0:109a7a5e3e6e 38
bracz 0:109a7a5e3e6e 39 uint8_t getcolor(uint8_t from, uint8_t to) {
bracz 0:109a7a5e3e6e 40 uint8_t result = 0x80;
bracz 0:109a7a5e3e6e 41 result |= getbit(from >> 0, to >> 0) << 0;
bracz 0:109a7a5e3e6e 42 result |= getbit(from >> 2, to >> 2) << 2;
bracz 0:109a7a5e3e6e 43 result |= getbit(from >> 4, to >> 4) << 4;
bracz 0:109a7a5e3e6e 44 return result;
bracz 0:109a7a5e3e6e 45 }
bracz 0:109a7a5e3e6e 46
bracz 0:109a7a5e3e6e 47
bracz 0:109a7a5e3e6e 48 void write_strip(uint8_t* data, int len) {
bracz 0:109a7a5e3e6e 49 latch = 0;
bracz 0:109a7a5e3e6e 50 for (int i = len - 1; i >= 0; i--) {
bracz 0:109a7a5e3e6e 51 spi.write(data[i]);
bracz 0:109a7a5e3e6e 52 }
bracz 0:109a7a5e3e6e 53 latch = 1;
bracz 0:109a7a5e3e6e 54 wait_us(2);
bracz 0:109a7a5e3e6e 55 latch = 0;
bracz 0:109a7a5e3e6e 56 }
bracz 0:109a7a5e3e6e 57
bracz 0:109a7a5e3e6e 58 class Schedulable {
bracz 0:109a7a5e3e6e 59 public:
bracz 0:109a7a5e3e6e 60 int time_;
bracz 0:109a7a5e3e6e 61 virtual void Run() = 0;
bracz 0:109a7a5e3e6e 62
bracz 0:109a7a5e3e6e 63 bool operator<(const Schedulable& o) const {
bracz 0:109a7a5e3e6e 64 return time_ < o.time_;
bracz 0:109a7a5e3e6e 65 }
bracz 0:109a7a5e3e6e 66 };
bracz 0:109a7a5e3e6e 67
bracz 0:109a7a5e3e6e 68
bracz 0:109a7a5e3e6e 69 struct comp {
bracz 0:109a7a5e3e6e 70 bool operator()(const Schedulable* a, const Schedulable* b) {
bracz 0:109a7a5e3e6e 71 return *b < *a;
bracz 0:109a7a5e3e6e 72 }
bracz 0:109a7a5e3e6e 73 };
bracz 0:109a7a5e3e6e 74
bracz 0:109a7a5e3e6e 75 priority_queue<Schedulable*, vector<Schedulable*>, comp> task_list;
bracz 0:109a7a5e3e6e 76
bracz 0:109a7a5e3e6e 77 void Schedule(Schedulable* action) {
bracz 0:109a7a5e3e6e 78 task_list.push(action);
bracz 0:109a7a5e3e6e 79 }
bracz 0:109a7a5e3e6e 80
bracz 0:109a7a5e3e6e 81 int global_tick = 0;
bracz 0:109a7a5e3e6e 82 bool strip_changed;
bracz 0:109a7a5e3e6e 83
bracz 0:109a7a5e3e6e 84 void tick_cb() {
bracz 0:109a7a5e3e6e 85 ++global_tick;
bracz 0:109a7a5e3e6e 86 strobe = !strobe;
bracz 0:109a7a5e3e6e 87 }
bracz 0:109a7a5e3e6e 88
bracz 0:109a7a5e3e6e 89 class RepeatedFadeInOut : public Schedulable {
bracz 0:109a7a5e3e6e 90 public:
bracz 0:109a7a5e3e6e 91 RepeatedFadeInOut(int start_time, int led, uint8_t a, uint8_t b, bool fast)
bracz 0:109a7a5e3e6e 92 : led_(led), a_(a), b_(b), fast_(fast) {
bracz 0:109a7a5e3e6e 93 time_ = start_time;
bracz 0:109a7a5e3e6e 94 Schedule(this);
bracz 0:109a7a5e3e6e 95 }
bracz 0:109a7a5e3e6e 96
bracz 0:109a7a5e3e6e 97 virtual void Run() {
bracz 0:109a7a5e3e6e 98 strip[led_] = getcolor(a_, b_);
bracz 0:109a7a5e3e6e 99 if (fast_) {
juliogerchman 2:590e99f4a313 100 strip[led_] |= FAST;
bracz 0:109a7a5e3e6e 101 time_ += 128;
bracz 0:109a7a5e3e6e 102 } else {
bracz 0:109a7a5e3e6e 103 time_ += 256;
bracz 0:109a7a5e3e6e 104 }
bracz 0:109a7a5e3e6e 105 strip_changed = true;
bracz 0:109a7a5e3e6e 106 swap(a_,b_);
bracz 0:109a7a5e3e6e 107 Schedule(this);
bracz 0:109a7a5e3e6e 108 }
juliogerchman 2:590e99f4a313 109
bracz 0:109a7a5e3e6e 110 private:
bracz 0:109a7a5e3e6e 111 int led_;
bracz 0:109a7a5e3e6e 112 uint8_t a_,b_;
bracz 0:109a7a5e3e6e 113 bool fast_;
bracz 0:109a7a5e3e6e 114 };
bracz 0:109a7a5e3e6e 115
bracz 1:1a0d5a780e57 116 class WalkingFadeInOut : public Schedulable {
bracz 1:1a0d5a780e57 117 public:
bracz 1:1a0d5a780e57 118 WalkingFadeInOut(int start_time, int led, int stride, uint8_t a, uint8_t b, bool fast)
bracz 1:1a0d5a780e57 119 : led_(led - stride), stride_(stride), a_(a), b_(b), fast_(fast), step_(true) {
bracz 1:1a0d5a780e57 120 time_ = start_time;
bracz 1:1a0d5a780e57 121 Schedule(this);
bracz 1:1a0d5a780e57 122 }
bracz 1:1a0d5a780e57 123
bracz 1:1a0d5a780e57 124 virtual void Run() {
bracz 1:1a0d5a780e57 125 if (step_) {
bracz 1:1a0d5a780e57 126 step_ = false;
bracz 1:1a0d5a780e57 127 if (led_ >= 0) strip[led_] = a_;
bracz 1:1a0d5a780e57 128 led_ += stride_;
bracz 1:1a0d5a780e57 129 led_ %= LENGTH;
bracz 1:1a0d5a780e57 130 } else {
bracz 1:1a0d5a780e57 131 step_ = true;
bracz 1:1a0d5a780e57 132 }
bracz 1:1a0d5a780e57 133 strip[led_] = getcolor(a_, b_);
bracz 1:1a0d5a780e57 134 if (fast_) {
juliogerchman 2:590e99f4a313 135 strip[led_] |= FAST;
bracz 1:1a0d5a780e57 136 time_ += 128;
bracz 1:1a0d5a780e57 137 } else {
bracz 1:1a0d5a780e57 138 time_ += 256;
bracz 1:1a0d5a780e57 139 }
bracz 1:1a0d5a780e57 140 strip_changed = true;
bracz 1:1a0d5a780e57 141 swap(a_,b_);
bracz 1:1a0d5a780e57 142 Schedule(this);
bracz 1:1a0d5a780e57 143 }
juliogerchman 2:590e99f4a313 144
bracz 1:1a0d5a780e57 145 private:
bracz 1:1a0d5a780e57 146 int led_, stride_;
bracz 1:1a0d5a780e57 147 uint8_t a_,b_;
bracz 1:1a0d5a780e57 148 bool fast_, step_;
bracz 1:1a0d5a780e57 149
bracz 1:1a0d5a780e57 150 };
bracz 1:1a0d5a780e57 151
juliogerchman 2:590e99f4a313 152 class RegionWalkingFadeInOut : public Schedulable {
juliogerchman 2:590e99f4a313 153 public:
juliogerchman 2:590e99f4a313 154 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 155 : 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 156 time_ = start_time;
juliogerchman 2:590e99f4a313 157 Schedule(this);
juliogerchman 2:590e99f4a313 158 }
bracz 1:1a0d5a780e57 159
juliogerchman 2:590e99f4a313 160 virtual void Run() {
juliogerchman 2:590e99f4a313 161 if (step_) {
juliogerchman 2:590e99f4a313 162 step_ = false;
juliogerchman 2:590e99f4a313 163 if (led_ >= 0) strip[led_ + start_led_] = a_;
juliogerchman 2:590e99f4a313 164 led_ += stride_;
juliogerchman 2:590e99f4a313 165 if (repeat_) {
juliogerchman 2:590e99f4a313 166 led_ %= length_;
juliogerchman 2:590e99f4a313 167 } else {
juliogerchman 3:42efa00ffef4 168 if (led_ >= length_) {
juliogerchman 3:42efa00ffef4 169 /*if (next_ && led_ == (length_ + stride_)) {
juliogerchman 2:590e99f4a313 170 next_->time_ = global_tick + 1;
juliogerchman 2:590e99f4a313 171 Schedule(next_);
juliogerchman 3:42efa00ffef4 172 }*/
juliogerchman 2:590e99f4a313 173 delete this;
juliogerchman 2:590e99f4a313 174 return;
juliogerchman 2:590e99f4a313 175 }
juliogerchman 2:590e99f4a313 176 }
juliogerchman 2:590e99f4a313 177 } else {
juliogerchman 3:42efa00ffef4 178 if (led_ == (length_ - 1) && drop_ && !repeat_) {
juliogerchman 2:590e99f4a313 179 if (next_) {
juliogerchman 3:42efa00ffef4 180 next_->time_ = global_tick + 257;
juliogerchman 2:590e99f4a313 181 Schedule(next_);
juliogerchman 2:590e99f4a313 182 }
juliogerchman 2:590e99f4a313 183 delete this;
juliogerchman 2:590e99f4a313 184 return;
juliogerchman 2:590e99f4a313 185 }
juliogerchman 2:590e99f4a313 186 step_ = true;
juliogerchman 2:590e99f4a313 187 }
juliogerchman 2:590e99f4a313 188 strip[led_ + start_led_] = getcolor(a_, b_);
juliogerchman 2:590e99f4a313 189 if (fast_) {
juliogerchman 2:590e99f4a313 190 strip[led_ + start_led_] |= FAST;
juliogerchman 2:590e99f4a313 191 time_ += 128;
juliogerchman 2:590e99f4a313 192 } else {
juliogerchman 2:590e99f4a313 193 time_ += 256;
juliogerchman 2:590e99f4a313 194 }
juliogerchman 2:590e99f4a313 195 strip_changed = true;
juliogerchman 2:590e99f4a313 196 swap(a_,b_);
juliogerchman 2:590e99f4a313 197 Schedule(this);
juliogerchman 2:590e99f4a313 198 }
juliogerchman 2:590e99f4a313 199
juliogerchman 2:590e99f4a313 200 private:
juliogerchman 2:590e99f4a313 201 int led_, stride_;
juliogerchman 2:590e99f4a313 202 int start_led_, length_;
juliogerchman 2:590e99f4a313 203 uint8_t a_,b_;
juliogerchman 2:590e99f4a313 204 bool fast_, step_;
juliogerchman 2:590e99f4a313 205 bool repeat_, drop_;
juliogerchman 2:590e99f4a313 206 Schedulable* next_;
juliogerchman 2:590e99f4a313 207 };
juliogerchman 2:590e99f4a313 208
juliogerchman 4:e3b6f5741d9d 209 class FadeFillRegion : public Schedulable {
juliogerchman 4:e3b6f5741d9d 210 public:
juliogerchman 4:e3b6f5741d9d 211 FadeFillRegion(int start_time, int start_led, int length, uint8_t from_color, uint8_t to_color, bool fast)
juliogerchman 4:e3b6f5741d9d 212 : start_led_(start_led), length_(length), from_color_(from_color), to_color_(to_color), fast_(fast) {
juliogerchman 4:e3b6f5741d9d 213 time_ = start_time;
juliogerchman 4:e3b6f5741d9d 214 Schedule(this);
juliogerchman 4:e3b6f5741d9d 215 }
juliogerchman 4:e3b6f5741d9d 216
juliogerchman 4:e3b6f5741d9d 217 virtual void Run() {
juliogerchman 4:e3b6f5741d9d 218 for (int i = start_led_; i < start_led_ + length_; ++i) {
juliogerchman 4:e3b6f5741d9d 219 strip[i] = getcolor(from_color_, to_color_) | (fast_ ? FAST : 0);
juliogerchman 4:e3b6f5741d9d 220 }
juliogerchman 4:e3b6f5741d9d 221 strip_changed = true;
juliogerchman 4:e3b6f5741d9d 222 delete this;
juliogerchman 4:e3b6f5741d9d 223 }
juliogerchman 4:e3b6f5741d9d 224
juliogerchman 4:e3b6f5741d9d 225 private:
juliogerchman 4:e3b6f5741d9d 226 int start_led_, length_;
juliogerchman 4:e3b6f5741d9d 227 uint8_t from_color_, to_color_;
juliogerchman 4:e3b6f5741d9d 228 bool fast_;
juliogerchman 4:e3b6f5741d9d 229 };
juliogerchman 4:e3b6f5741d9d 230
juliogerchman 2:590e99f4a313 231 /* Keep dropping water drops in a bucket, until it fills up. */
juliogerchman 2:590e99f4a313 232 class DropBucketFill : public Schedulable {
juliogerchman 2:590e99f4a313 233 public:
juliogerchman 4:e3b6f5741d9d 234 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)
juliogerchman 4:e3b6f5741d9d 235 : 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) {
juliogerchman 2:590e99f4a313 236 time_ = start_time;
juliogerchman 2:590e99f4a313 237 Schedule(this);
juliogerchman 2:590e99f4a313 238 }
juliogerchman 2:590e99f4a313 239
juliogerchman 2:590e99f4a313 240 virtual void Run() {
juliogerchman 2:590e99f4a313 241 // The bucket starts with a drop at its end.
juliogerchman 2:590e99f4a313 242 //strip[start_led_ + length_] = to_color_;
juliogerchman 2:590e99f4a313 243 //strip[start_led_ + length_] = RED;
juliogerchman 2:590e99f4a313 244 if (length_ > 0) {
juliogerchman 2:590e99f4a313 245 // There's still space in the bucket. Drop a new drop.
juliogerchman 3:42efa00ffef4 246 for (int i = 0; i < min(drop_size_, length_); ++i) {
juliogerchman 4:e3b6f5741d9d 247 Schedulable* next_drop = this;
juliogerchman 3:42efa00ffef4 248 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 249 }
juliogerchman 2:590e99f4a313 250 length_--;
juliogerchman 2:590e99f4a313 251 } else {
juliogerchman 2:590e99f4a313 252 // There's no more space in the bucket. Bail out.
juliogerchman 4:e3b6f5741d9d 253 new FadeFillRegion(global_tick + fade_out_pause_, start_led_, original_length_, to_color_, fade_out_color_, false);
juliogerchman 2:590e99f4a313 254 delete this;
juliogerchman 2:590e99f4a313 255 return;
juliogerchman 2:590e99f4a313 256 }
juliogerchman 2:590e99f4a313 257 }
juliogerchman 2:590e99f4a313 258
juliogerchman 2:590e99f4a313 259 private:
juliogerchman 4:e3b6f5741d9d 260 int start_led_, length_, original_length_;
juliogerchman 2:590e99f4a313 261 int drop_size_;
juliogerchman 2:590e99f4a313 262 uint8_t from_color_, to_color_;
juliogerchman 4:e3b6f5741d9d 263 int fade_out_pause_;
juliogerchman 4:e3b6f5741d9d 264 uint8_t fade_out_color_;
juliogerchman 2:590e99f4a313 265 };
juliogerchman 2:590e99f4a313 266
juliogerchman 2:590e99f4a313 267 void init_board() {
bracz 0:109a7a5e3e6e 268 pc.baud(115200);
bracz 0:109a7a5e3e6e 269
bracz 0:109a7a5e3e6e 270 myled = 0;
bracz 0:109a7a5e3e6e 271 latch = 0;
bracz 0:109a7a5e3e6e 272
bracz 0:109a7a5e3e6e 273 spi.format(8, 0);
bracz 0:109a7a5e3e6e 274 spi.frequency(300000);
bracz 0:109a7a5e3e6e 275 wait_ms(500);
bracz 0:109a7a5e3e6e 276 myled = 1;
juliogerchman 2:590e99f4a313 277 memset(strip, BLACK, sizeof(strip));
bracz 0:109a7a5e3e6e 278 write_strip(strip, sizeof(strip));
juliogerchman 2:590e99f4a313 279 g_ticker.attach(&tick_cb, 1.0/1000);
bracz 0:109a7a5e3e6e 280
bracz 0:109a7a5e3e6e 281 memset(strip, 0x0, sizeof(strip));
juliogerchman 2:590e99f4a313 282 }
juliogerchman 2:590e99f4a313 283
juliogerchman 2:590e99f4a313 284 void run_loop() {
bracz 0:109a7a5e3e6e 285 while(1) {
bracz 0:109a7a5e3e6e 286 while (task_list.empty() || global_tick < task_list.top()->time_) {
bracz 0:109a7a5e3e6e 287 if (strip_changed) {
bracz 0:109a7a5e3e6e 288 write_strip(strip, sizeof(strip));
bracz 0:109a7a5e3e6e 289 strip_changed = false;
bracz 0:109a7a5e3e6e 290 memset(strip, 0x0, sizeof(strip));
bracz 0:109a7a5e3e6e 291 }
bracz 0:109a7a5e3e6e 292 }
bracz 0:109a7a5e3e6e 293 Schedulable* action = task_list.top();
bracz 0:109a7a5e3e6e 294 task_list.pop();
bracz 0:109a7a5e3e6e 295 action->Run();
bracz 0:109a7a5e3e6e 296 }
juliogerchman 2:590e99f4a313 297 }
bracz 0:109a7a5e3e6e 298
juliogerchman 2:590e99f4a313 299 int main() {
juliogerchman 2:590e99f4a313 300 init_board();
bracz 0:109a7a5e3e6e 301
juliogerchman 2:590e99f4a313 302 int stride = 7;
juliogerchman 2:590e99f4a313 303 for (int i = 0; i < stride; i++) {
juliogerchman 2:590e99f4a313 304 //new WalkingFadeInOut((256 * i / stride), i, stride, BLACK, RED, true);
juliogerchman 2:590e99f4a313 305 /* new RepeatedFadeInOut(0, i, BLACK, RED, false); */
juliogerchman 2:590e99f4a313 306 //new RegionWalkingFadeInOut((256 * i / stride), i, stride, 5, 30, BLACK, BLUE, true, false);
bracz 0:109a7a5e3e6e 307 }
juliogerchman 2:590e99f4a313 308
juliogerchman 4:e3b6f5741d9d 309 new DropBucketFill(0, 10, 20, 3, BLACK, BLUE, 2560, BLACK);
juliogerchman 4:e3b6f5741d9d 310 new DropBucketFill(0, 30, 20, 11, BLACK, GREEN, 2560, BLACK);
juliogerchman 3:42efa00ffef4 311
juliogerchman 2:590e99f4a313 312 run_loop();
juliogerchman 2:590e99f4a313 313 }