├── Creepers.cpp ├── Creepers.h ├── Cylon.cpp ├── Cylon.h ├── Eyes.cpp ├── Eyes.h ├── G35.cpp ├── G35.h ├── G35String.cpp ├── G35String.h ├── G35StringGroup.cpp ├── G35StringGroup.h ├── HalloweenPrograms.cpp ├── HalloweenPrograms.h ├── Inchworm.cpp ├── Inchworm.h ├── LICENSE ├── LightProgram.h ├── MEOPrograms.cpp ├── MEOPrograms.h ├── Meteorite.cpp ├── Meteorite.h ├── Orbit.cpp ├── Orbit.h ├── Orbiter.cpp ├── Orbiter.h ├── PlusPrograms.cpp ├── PlusPrograms.h ├── ProgramRunner.h ├── Pulse.cpp ├── Pulse.h ├── PumpkinChase.cpp ├── PumpkinChase.h ├── README.md ├── Rainbow.cpp ├── Rainbow.h ├── RedGreenChase.cpp ├── RedGreenChase.h ├── SpookyFlicker.cpp ├── SpookyFlicker.h ├── SpookySlow.cpp ├── SpookySlow.h ├── Stereo.cpp ├── Stereo.h ├── StockPrograms.cpp ├── StockPrograms.h ├── Twinkle.cpp ├── Twinkle.h ├── ValentinesDay.cpp ├── Worm.cpp ├── Worm.h ├── examples ├── BasicExample │ └── BasicExample.ino ├── Go49ers2013 │ └── Go49ers2013.ino ├── MultipleIndependentStrings │ └── MultipleIndependentStrings.ino ├── MultipleStringsAsOne │ └── MultipleStringsAsOne.ino ├── StockPlus │ └── StockPlus.ino ├── Ticon2011 │ └── Ticon2011.ino ├── TiconHalloween2012 │ └── TiconHalloween2012.ino └── TiconXmas2012 │ └── TiconXmas2012.ino ├── images └── green_lights.jpg └── keywords.txt /Creepers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | Creepers::Creepers(G35& g35) : LightProgram(g35), count_(0), next_worm_(0) { 14 | g35_.fill_color(0, light_count_, 255, COLOR_BLACK); 15 | } 16 | 17 | uint32_t Creepers::Do() { 18 | for (int i = 0; i < count_; ++i) { 19 | worms_[i].Do(g35_); 20 | } 21 | if (count_ < 6 && millis() > next_worm_) { 22 | ++count_; 23 | worms_[count_ - 1].set_color(rand() & 1 ? COLOR_GREEN : COLOR_ORANGE); 24 | next_worm_ = millis() + 2000 + 1000 * count_; 25 | } 26 | return bulb_frame_; 27 | } 28 | -------------------------------------------------------------------------------- /Creepers.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_CREEPERS_H 12 | #define INCLUDE_G35_PROGRAMS_CREEPERS_H 13 | 14 | #include 15 | #include 16 | 17 | // Inchworm with Halloween colors. :| 18 | class Creepers : public LightProgram { 19 | public: 20 | Creepers(G35& g35); 21 | uint32_t Do(); 22 | 23 | private: 24 | uint8_t count_; 25 | uint32_t next_worm_; 26 | Worm worms_[6]; 27 | }; 28 | 29 | #endif // INCLUDE_G35_PROGRAMS_CREEPERS_H 30 | -------------------------------------------------------------------------------- /Cylon.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | Cylon::Cylon(G35& g35) : LightProgram(g35), orbiter_(0.5, 0.01), last_x_(0) {} 14 | 15 | uint32_t Cylon::Do() { 16 | orbiter_.Do(); 17 | uint8_t x = orbiter_.x_local(light_count_, light_count_ >> 1); 18 | 19 | if (last_x_ != x) { 20 | g35_.set_color(last_x_, 255, COLOR_BLACK); 21 | last_x_ = x; 22 | } 23 | g35_.set_color(x, 255, orbiter_.color()); 24 | 25 | return bulb_frame_ >> 1; 26 | } 27 | -------------------------------------------------------------------------------- /Cylon.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_CYLON_H 12 | #define INCLUDE_G35_PROGRAMS_CYLON_H 13 | 14 | #include 15 | #include 16 | 17 | class Cylon : public LightProgram { 18 | public: 19 | Cylon(G35& g35); 20 | 21 | uint32_t Do(); 22 | 23 | private: 24 | Orbiter orbiter_; 25 | uint8_t last_x_; 26 | }; 27 | 28 | #endif // INCLUDE_G35_PROGRAMS_CYLON_H 29 | -------------------------------------------------------------------------------- /Eyes.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | Eyes::Eyes(G35& g35) : LightProgram(g35), count_(0), next_eye_(0) { 14 | g35_.fill_color(0, light_count_, 255, COLOR_BLACK); 15 | 16 | while (3 * EYE_COUNT >= light_count_) { 17 | // There isn't enough room on the light string for this many eyes. 18 | } 19 | 20 | for (int i = 0; i < EYE_COUNT; ++i) { 21 | uint16_t new_position; 22 | do { 23 | new_position = rand() % (light_count_ - 1); 24 | for (int j = 0; j < i; ++j) { 25 | uint16_t occupied_position = eyes_[j].get_position(); 26 | if (new_position >= occupied_position - 1 && 27 | new_position <= occupied_position + 1) { 28 | new_position = light_count_; 29 | break; 30 | } 31 | } 32 | } while (new_position == light_count_); 33 | eyes_[i].set_position(new_position); 34 | } 35 | } 36 | 37 | uint32_t Eyes::Do() { 38 | for (int i = 0; i < count_; ++i) { 39 | eyes_[i].Do(g35_); 40 | } 41 | if (count_ < EYE_COUNT && millis() > next_eye_) { 42 | ++count_; 43 | next_eye_ = millis() + 2000 + 1000 * count_; 44 | } 45 | return bulb_frame_; 46 | } 47 | -------------------------------------------------------------------------------- /Eyes.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_EYES_H 12 | #define INCLUDE_G35_PROGRAMS_EYES_H 13 | 14 | #include 15 | 16 | class Eye { 17 | public: 18 | Eye() 19 | : color_(COLOR_BLACK), position_(0), next_blink_(0), state_(INIT) { 20 | switch (rand() % 4) { 21 | case 0: color_ = COLOR_ORANGE; break; 22 | case 1: color_ = COLOR_RED; break; 23 | case 2: color_ = COLOR_INDIGO; break; 24 | case 3: color_ = COLOR_GREEN; break; 25 | } 26 | } 27 | 28 | uint16_t get_position() { return position_; } 29 | void set_position(uint16_t value) { position_ = value; } 30 | 31 | void Do(G35& g35) { 32 | if (state_ == INIT) { 33 | state_ = WATCHING; 34 | } 35 | uint32_t now = millis(); 36 | if (next_blink_ < now) { 37 | if (state_ == BLINKING) { 38 | g35.fill_color(position_, 2, G35::MAX_INTENSITY, color_); 39 | next_blink_ = now + 3000 + (rand() % 3000); 40 | state_ = WATCHING; 41 | } else { 42 | g35.fill_color(position_, 2, G35::MAX_INTENSITY, COLOR_BLACK); 43 | next_blink_ = now + 100; 44 | state_ = BLINKING; 45 | } 46 | } 47 | } 48 | 49 | private: 50 | enum { 51 | INIT, WATCHING, BLINKING 52 | }; 53 | 54 | color_t color_; 55 | uint16_t position_; 56 | uint32_t next_blink_; 57 | uint8_t state_; 58 | }; 59 | 60 | class Eyes : public LightProgram { 61 | public: 62 | Eyes(G35& g35); 63 | uint32_t Do(); 64 | 65 | private: 66 | enum { EYE_COUNT = 10 }; 67 | 68 | uint8_t count_; 69 | uint32_t next_eye_; 70 | Eye eyes_[EYE_COUNT]; 71 | }; 72 | 73 | #endif // INCLUDE_G35_PROGRAMS_EYES_H 74 | -------------------------------------------------------------------------------- /G35.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | 4 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 5 | subject to the BSD license as described in the accompanying LICENSE file. 6 | 7 | Original version by Paul Martis (http://www.digitalmisery.com). See 8 | README for complete attributions. 9 | 10 | Special thanks to Richard and "slinky" for the unrolled- 11 | loop protocol code that seems to work very well! 12 | */ 13 | 14 | #include 15 | 16 | G35::G35() : light_count_(0) { 17 | } 18 | 19 | bool G35::set_color_if_in_range(uint8_t position, uint8_t intensity, 20 | color_t color) { 21 | if (position >= light_count_) { 22 | return false; 23 | } 24 | set_color(position, intensity, color); 25 | return true; 26 | } 27 | 28 | // Returns 12-bit color from red, green, and blue components 29 | color_t G35::color(uint8_t r, uint8_t g, uint8_t b) { 30 | return COLOR(r, g, b); 31 | } 32 | 33 | color_t G35::color_hue(uint8_t h) { 34 | switch (h >> 4) { 35 | case 0: h -= 0; return color(h, CHANNEL_MAX, 0); 36 | case 1: h -= 16; return color(CHANNEL_MAX, (CHANNEL_MAX - h), 0); 37 | case 2: h -= 32; return color(CHANNEL_MAX, 0, h); 38 | case 3: h -= 48; return color((CHANNEL_MAX - h), 0, CHANNEL_MAX); 39 | case 4: h -= 64; return color(0, h, CHANNEL_MAX); 40 | case 5: h -= 80; return color(0, CHANNEL_MAX, (CHANNEL_MAX - h)); 41 | default: 42 | return COLOR_WHITE; 43 | } 44 | } 45 | 46 | void G35::fill_color(uint8_t begin, uint8_t count, 47 | uint8_t intensity, color_t color) { 48 | while (count--) { 49 | set_color(begin++, intensity, color); 50 | } 51 | } 52 | 53 | void G35::fill_random_max(uint8_t begin, uint8_t count, uint8_t intensity) { 54 | while (count--) { 55 | set_color(begin++, intensity, max_color(rand())); 56 | } 57 | } 58 | 59 | void G35::fill_sequence(uint8_t begin, uint8_t count, 60 | uint16_t sequence, uint8_t span_size, 61 | uint8_t intensity, 62 | color_t (*sequence_func)(uint16_t sequence)) { 63 | while (count--) { 64 | set_color(begin + count, intensity, sequence_func(sequence++ / span_size)); 65 | } 66 | } 67 | 68 | void G35::fill_sequence(uint16_t sequence, uint8_t span_size, 69 | uint8_t intensity, 70 | color_t (*sequence_func)(uint16_t sequence)) { 71 | fill_sequence(0, light_count_, sequence, span_size, intensity, sequence_func); 72 | } 73 | 74 | void G35::fill_sequence(uint8_t begin, uint8_t count, 75 | uint16_t sequence, uint8_t span_size, 76 | bool (*sequence_func)(uint16_t sequence, color_t& color, 77 | uint8_t& intensity)) { 78 | while (count--) { 79 | color_t color; 80 | uint8_t intensity; 81 | sequence_func(sequence++ / span_size, color, intensity); 82 | set_color(begin + count, intensity, color); 83 | } 84 | } 85 | 86 | color_t G35::rainbow_color(uint16_t color) { 87 | if (color >= RB_COUNT) { 88 | color = color % RB_COUNT; 89 | } 90 | switch (color) { 91 | case RB_RED: 92 | return COLOR_RED; 93 | case RB_ORANGE: 94 | return COLOR_ORANGE; 95 | case RB_YELLOW: 96 | return COLOR_YELLOW; 97 | case RB_GREEN: 98 | return COLOR_GREEN; 99 | case RB_BLUE: 100 | return COLOR_BLUE; 101 | case RB_INDIGO: 102 | return COLOR_INDIGO; 103 | case RB_VIOLET: 104 | return COLOR_VIOLET; 105 | default: 106 | return COLOR_WHITE; 107 | } 108 | } 109 | 110 | color_t G35::max_color(uint16_t color) { 111 | if (color >= 7) { 112 | color = color % 7; 113 | } 114 | switch (color) { 115 | case 0: 116 | return COLOR_RED; 117 | case 1: 118 | return COLOR_GREEN; 119 | case 2: 120 | return COLOR_BLUE; 121 | case 3: 122 | return COLOR_CYAN; 123 | case 4: 124 | return COLOR_MAGENTA; 125 | case 5: 126 | return COLOR_YELLOW; 127 | default: 128 | return COLOR_WHITE; 129 | } 130 | } 131 | 132 | void G35::broadcast_intensity(uint8_t intensity) { 133 | set_color(get_broadcast_bulb(), intensity, COLOR_BLACK); 134 | } 135 | -------------------------------------------------------------------------------- /G35.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | Original version by Paul Martis (http://www.digitalmisery.com). See 7 | README for complete attributions. 8 | */ 9 | 10 | #ifndef INCLUDE_G35_ARDUINO_H 11 | #define INCLUDE_G35_ARDUINO_H 12 | 13 | #include 14 | 15 | #define color_t uint16_t 16 | #define CHANNEL_MAX (0xF) // Each color channel is 4-bit 17 | #define HUE_MAX ((CHANNEL_MAX + 1) * 6 - 1) 18 | 19 | // Color is 12-bit (4-bit each R, G, B) 20 | #define COLOR(r, g, b) ((r) + ((g) << 4) + ((b) << 8)) 21 | #define COLOR_WHITE COLOR(CHANNEL_MAX, CHANNEL_MAX, CHANNEL_MAX) 22 | #define COLOR_BLACK COLOR(0, 0, 0) 23 | #define COLOR_RED COLOR(CHANNEL_MAX, 0, 0) 24 | #define COLOR_GREEN COLOR(0, CHANNEL_MAX, 0) 25 | #define COLOR_BLUE COLOR(0, 0, CHANNEL_MAX) 26 | #define COLOR_CYAN COLOR(0,CHANNEL_MAX, CHANNEL_MAX) 27 | #define COLOR_MAGENTA COLOR(CHANNEL_MAX, 0,CHANNEL_MAX) 28 | #define COLOR_YELLOW COLOR(CHANNEL_MAX,CHANNEL_MAX, 0) 29 | #define COLOR_PURPLE COLOR(0xa, 0x3, 0xd) 30 | #define COLOR_ORANGE COLOR(0xf, 0x1, 0x0) 31 | #define COLOR_PALE_ORANGE COLOR(0x8, 0x1, 0x0) 32 | #define COLOR_WARMWHITE COLOR(0xf, 0x7, 0x2) 33 | #define COLOR_INDIGO COLOR(0x6, 0, 0xf) 34 | #define COLOR_VIOLET COLOR(0x8, 0, 0xf) 35 | 36 | // G35 is an abstract class representing a string of G35 lights of arbitrary 37 | // length. LightPrograms talk to this interface. 38 | class G35 { 39 | public: 40 | G35(); 41 | 42 | enum { 43 | // This is an abstraction leak. The choice was either to define a scaling 44 | // function that mapped [0..255] to [0..0xcc], or just to leak a hardware 45 | // detail through to this interface. We chose pragmatism. 46 | MAX_INTENSITY = 0xcc 47 | }; 48 | 49 | enum { 50 | RB_RED = 0, 51 | RB_ORANGE, 52 | RB_YELLOW, 53 | RB_GREEN, 54 | RB_BLUE, 55 | RB_INDIGO, 56 | RB_VIOLET 57 | }; 58 | 59 | enum { 60 | RB_FIRST = RB_RED, 61 | RB_LAST = RB_VIOLET, 62 | RB_COUNT = RB_LAST + 1 63 | }; 64 | 65 | virtual uint16_t get_light_count() = 0; 66 | virtual uint16_t get_last_light() { return get_light_count() - 1; } 67 | virtual uint16_t get_halfway_point() { return get_light_count() / 2; } 68 | 69 | // One bulb's share of a second, in milliseconds 70 | virtual uint8_t get_bulb_frame() { return 1000 / get_light_count(); } 71 | 72 | // Turn on a specific LED with a color and brightness 73 | virtual void set_color(uint8_t bulb, uint8_t intensity, color_t color) = 0; 74 | 75 | // Like set_color, but doesn't explode with positions out of range 76 | virtual bool set_color_if_in_range(uint8_t led, uint8_t intensity, 77 | color_t color); 78 | 79 | // Color data type 80 | static color_t color(uint8_t r, uint8_t g, uint8_t b); 81 | 82 | // Returns primary hue colors 83 | static color_t color_hue(uint8_t h); 84 | 85 | static color_t rainbow_color(uint16_t color); 86 | 87 | // Given an int value, returns a "max" color (one with R/G/B each set to 88 | // 0 or 255, except for black). The mapping is arbitary but deterministic. 89 | static color_t max_color(uint16_t color); 90 | 91 | // Make all LEDs the same color starting at specified beginning LED 92 | virtual void fill_color(uint8_t begin, uint8_t count, uint8_t intensity, 93 | color_t color); 94 | virtual void fill_random_max(uint8_t begin, uint8_t count, uint8_t intensity); 95 | 96 | virtual void fill_sequence(uint16_t sequence, uint8_t span_size, 97 | uint8_t intensity, 98 | color_t (*sequence_func)(uint16_t sequence)); 99 | virtual void fill_sequence(uint8_t begin, uint8_t count, uint16_t sequence, 100 | uint8_t span_size, uint8_t intensity, 101 | color_t (*sequence_func)(uint16_t sequence)); 102 | virtual void fill_sequence(uint8_t begin, uint8_t count, uint16_t sequence, 103 | uint8_t span_size, 104 | bool (*sequence_func)(uint16_t sequence, 105 | color_t& color, 106 | uint8_t& intensity)); 107 | virtual void broadcast_intensity(uint8_t intensity); 108 | 109 | protected: 110 | uint16_t light_count_; 111 | 112 | virtual uint8_t get_broadcast_bulb() = 0; 113 | }; 114 | 115 | #endif // INCLUDE_G35_ARDUINO_H 116 | -------------------------------------------------------------------------------- /G35String.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | 4 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 5 | subject to the BSD license as described in the accompanying LICENSE file. 6 | 7 | Original version by Paul Martis (http://www.digitalmisery.com). See 8 | README for complete attributions. 9 | 10 | Special thanks to Richard and "slinky" for the unrolled- 11 | loop protocol code that seems to work very well! 12 | */ 13 | 14 | #include 15 | 16 | #define MHZ_16 (1) // standard Arduino/Teensy 17 | 18 | #if MHZ_16 19 | #define DELAYLONG 17 // should be ~ 20uS long 20 | #define DELAYSHORT 7 // should be ~ 10uS long 21 | #else // 20MHz 22 | #define DELAYLONG 25 // should be ~ 20uS long 23 | #define DELAYSHORT 11 // should be ~ 10uS long 24 | #endif 25 | #define DELAYEND 40 // should be ~ 30uS long 26 | 27 | #define ZERO(x) digitalWrite(x, LOW); \ 28 | delayMicroseconds(DELAYSHORT); \ 29 | digitalWrite(x, HIGH); \ 30 | delayMicroseconds(DELAYLONG); 31 | 32 | #define ONE(x) digitalWrite(x, LOW); \ 33 | delayMicroseconds(DELAYLONG); \ 34 | digitalWrite(x, HIGH); \ 35 | delayMicroseconds(DELAYSHORT); 36 | 37 | G35String::G35String(uint8_t pin, uint8_t light_count, 38 | uint8_t physical_light_count, 39 | uint8_t bulb_zero, bool is_forward) 40 | : G35(), pin_(pin), physical_light_count_(physical_light_count), 41 | bulb_zero_(bulb_zero), is_forward_(is_forward) { 42 | pinMode(pin, OUTPUT); 43 | light_count_ = light_count; 44 | } 45 | 46 | G35String::G35String(uint8_t pin, uint8_t light_count) 47 | : G35(), pin_(pin), physical_light_count_(light_count), 48 | bulb_zero_(0), is_forward_(true) { 49 | pinMode(pin, OUTPUT); 50 | light_count_ = light_count; 51 | } 52 | 53 | void G35String::set_color(uint8_t bulb, uint8_t intensity, color_t color) { 54 | bulb += bulb_zero_; 55 | uint8_t r, g, b; 56 | r = color & 0x0F; 57 | g = (color >> 4) & 0x0F; 58 | b = (color >> 8) & 0x0F; 59 | 60 | if (intensity > MAX_INTENSITY) { 61 | intensity = MAX_INTENSITY; 62 | } 63 | 64 | noInterrupts(); 65 | 66 | digitalWrite(pin_, HIGH); 67 | delayMicroseconds(DELAYSHORT); 68 | 69 | // LED Address 70 | if (bulb & 0x20) { ONE(pin_); } else { ZERO(pin_); } 71 | if (bulb & 0x10) { ONE(pin_); } else { ZERO(pin_); } 72 | if (bulb & 0x08) { ONE(pin_); } else { ZERO(pin_); } 73 | if (bulb & 0x04) { ONE(pin_); } else { ZERO(pin_); } 74 | if (bulb & 0x02) { ONE(pin_); } else { ZERO(pin_); } 75 | if (bulb & 0x01) { ONE(pin_); } else { ZERO(pin_); } 76 | 77 | // Brightness 78 | if (intensity & 0x80) { ONE(pin_); } else { ZERO(pin_); } 79 | if (intensity & 0x40) { ONE(pin_); } else { ZERO(pin_); } 80 | if (intensity & 0x20) { ONE(pin_); } else { ZERO(pin_); } 81 | if (intensity & 0x10) { ONE(pin_); } else { ZERO(pin_); } 82 | if (intensity & 0x08) { ONE(pin_); } else { ZERO(pin_); } 83 | if (intensity & 0x04) { ONE(pin_); } else { ZERO(pin_); } 84 | if (intensity & 0x02) { ONE(pin_); } else { ZERO(pin_); } 85 | if (intensity & 0x01) { ONE(pin_); } else { ZERO(pin_); } 86 | 87 | // Blue 88 | if (b & 0x8) { ONE(pin_); } else { ZERO(pin_); } 89 | if (b & 0x4) { ONE(pin_); } else { ZERO(pin_); } 90 | if (b & 0x2) { ONE(pin_); } else { ZERO(pin_); } 91 | if (b & 0x1) { ONE(pin_); } else { ZERO(pin_); } 92 | 93 | // Green 94 | if (g & 0x8) { ONE(pin_); } else { ZERO(pin_); } 95 | if (g & 0x4) { ONE(pin_); } else { ZERO(pin_); } 96 | if (g & 0x2) { ONE(pin_); } else { ZERO(pin_); } 97 | if (g & 0x1) { ONE(pin_); } else { ZERO(pin_); } 98 | 99 | // Red 100 | if (r & 0x8) { ONE(pin_); } else { ZERO(pin_); } 101 | if (r & 0x4) { ONE(pin_); } else { ZERO(pin_); } 102 | if (r & 0x2) { ONE(pin_); } else { ZERO(pin_); } 103 | if (r & 0x1) { ONE(pin_); } else { ZERO(pin_); } 104 | 105 | digitalWrite(pin_, LOW); 106 | delayMicroseconds(DELAYEND); 107 | 108 | interrupts(); 109 | } 110 | 111 | void G35String::enumerate() { 112 | enumerate(is_forward_); 113 | } 114 | 115 | void G35String::enumerate(bool forward) { 116 | uint8_t count = physical_light_count_; 117 | uint8_t bulb = forward ? 0 : light_count_ - 1; 118 | int8_t delta = forward ? 1 : -1; 119 | while (count--) { 120 | set_color(bulb, MAX_INTENSITY, COLOR_RED); 121 | bulb += delta; 122 | } 123 | } 124 | 125 | void G35String::enumerate_forward() { 126 | enumerate(true); 127 | } 128 | 129 | void G35String::enumerate_reverse() { 130 | enumerate(false); 131 | } 132 | 133 | void G35String::do_test_patterns() { 134 | const uint8_t last_light = light_count_ - 1; 135 | 136 | // Cycle through primaries. 137 | fill_color(0, light_count_, MAX_INTENSITY, COLOR_RED); 138 | delay(1000); 139 | fill_color(0, light_count_, MAX_INTENSITY, COLOR_GREEN); 140 | delay(1000); 141 | fill_color(0, light_count_, MAX_INTENSITY, COLOR_BLUE); 142 | delay(1000); 143 | 144 | // Tickle the ends. You should see three reds at the start, and three greens 145 | // at the end. This confirms that you've properly configured the strand 146 | // lengths and directions. 147 | for (int i = 0; i < 8; ++i) { 148 | for (int j = 0; j < 3; ++j) { 149 | set_color(BROADCAST_BULB, 0, COLOR_BLACK); 150 | set_color(j, MAX_INTENSITY, COLOR_RED); 151 | set_color(last_light - j, MAX_INTENSITY, COLOR_GREEN); 152 | delay(250); 153 | } 154 | } 155 | 156 | // Full white for five seconds. If you have power problems, they'll probably 157 | // show up here. 158 | fill_color(0, light_count_, MAX_INTENSITY, COLOR_WHITE); 159 | delay(5000); 160 | 161 | // Cycle through secondaries. 162 | fill_color(0, light_count_, MAX_INTENSITY, COLOR_YELLOW); 163 | delay(1000); 164 | fill_color(0, light_count_, MAX_INTENSITY, COLOR_CYAN); 165 | delay(1000); 166 | fill_color(0, light_count_, MAX_INTENSITY, COLOR_MAGENTA); 167 | delay(1000); 168 | 169 | // ... and get ready for the first program. 170 | fill_color(0, light_count_, MAX_INTENSITY, COLOR_BLACK); 171 | } 172 | -------------------------------------------------------------------------------- /G35String.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | Original version by Paul Martis (http://www.digitalmisery.com). See 7 | README for complete attributions. 8 | */ 9 | 10 | #ifndef INCLUDE_G35_STRING_H 11 | #define INCLUDE_G35_STRING_H 12 | 13 | #include 14 | 15 | // A G35String knows how to talk to a real GE Color Effects light string. 16 | // In particular, it implements the set_color() method of the G35 interface. 17 | // 18 | // These strings need enumerate() to be called before anything else, so that 19 | // each bulb has an individual address. In many cases, your lights will work 20 | // as expected even if you forget to call enumerate(), because most programs 21 | // happen to do the same thing as enumerate() -- namely, they send commands 22 | // to all bulbs starting with bulb #0 and ending with bulb #N-1. If your 23 | // light programs look right but fractured, it's because you forgot to call 24 | // enumerate(). 25 | class G35String : public G35 { 26 | public: 27 | // |pin|: the Arduino pin driving this string's data line. 28 | // |light_count|: the number of visible, physical bulbs on the string. 29 | // |physical_light_count|: the number of physical bulbs on the string. 30 | // |bulb_zero|: the index of the first bulb (almost always zero). 31 | // |is_forward|: true if the closest bulb to the plug has the lowest index. 32 | G35String(uint8_t pin, uint8_t light_count, uint8_t physical_light_count, 33 | uint8_t bulb_zero, bool is_forward); 34 | G35String(uint8_t pin, uint8_t light_count); 35 | 36 | // Implementation of G35 interface. 37 | virtual uint16_t get_light_count() { return light_count_; } 38 | void set_color(uint8_t led, uint8_t intensity, color_t color); 39 | 40 | // Initialize lights by giving them each an address. 41 | void enumerate(); 42 | 43 | // Displays known-good patterns. Useful to prevent insanity during hardware 44 | // debugging. 45 | void do_test_patterns(); 46 | 47 | protected: 48 | virtual uint8_t get_broadcast_bulb() { return BROADCAST_BULB; } 49 | 50 | private: 51 | uint8_t pin_; 52 | uint8_t physical_light_count_; 53 | uint8_t bulb_zero_; 54 | bool is_forward_; 55 | 56 | enum { 57 | MAX_INTENSITY = 0xcc, 58 | BROADCAST_BULB = 63, 59 | }; 60 | 61 | // Initialize lights by giving them each an address. enumerate_forward() 62 | // numbers the bulb closest to the controller 0, and enumerate_reverse() 63 | // numbers the farthest bulb 0. 64 | void enumerate(bool reverse); 65 | void enumerate_forward(); 66 | void enumerate_reverse(); 67 | 68 | // Low-level one-wire protocol commands 69 | void begin(); 70 | void one(); 71 | void zero(); 72 | void end(); 73 | }; 74 | 75 | #endif // INCLUDE_G35_STRING_H 76 | -------------------------------------------------------------------------------- /G35StringGroup.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | Original version by Paul Martis (http://www.digitalmisery.com). See 7 | README for complete attributions. 8 | */ 9 | 10 | #include 11 | 12 | G35StringGroup::G35StringGroup() 13 | : string_count_(0) { 14 | light_count_ = 0; 15 | } 16 | 17 | void G35StringGroup::AddString(G35* g35) { 18 | if (string_count_ == MAX_STRINGS) { 19 | return; 20 | } 21 | uint16_t light_count = g35->get_light_count(); 22 | string_offsets_[string_count_] = 23 | string_count_ == 0 ? 24 | light_count : 25 | string_offsets_[string_count_ - 1] + light_count; 26 | strings_[string_count_] = g35; 27 | ++string_count_; 28 | light_count_ += light_count; 29 | } 30 | 31 | uint16_t G35StringGroup::get_light_count() { 32 | return light_count_; 33 | } 34 | 35 | void G35StringGroup::set_color(uint8_t bulb, uint8_t intensity, color_t color) { 36 | uint8_t string = 0; 37 | while (bulb >= string_offsets_[string] && string < string_count_) { 38 | string++; 39 | } 40 | if (string < string_count_) { 41 | if (string > 0) { 42 | bulb -= string_offsets_[string - 1]; 43 | } 44 | strings_[string]->set_color(bulb, intensity, color); 45 | } else { 46 | // A program is misbehaving. 47 | #if 0 48 | Serial.println("out of bounds"); 49 | #endif 50 | } 51 | } 52 | 53 | void G35StringGroup::broadcast_intensity(uint8_t intensity) { 54 | for (uint8_t i = 0; i < string_count_; ++i) { 55 | strings_[i]->broadcast_intensity(intensity); 56 | } 57 | } 58 | 59 | uint8_t G35StringGroup::get_broadcast_bulb() { 60 | return 0; // In this implementation, shouldn't ever be called. 61 | } 62 | -------------------------------------------------------------------------------- /G35StringGroup.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | Original version by Paul Martis (http://www.digitalmisery.com). See 7 | README for complete attributions. 8 | */ 9 | 10 | #ifndef INCLUDE_G35_STRING_GROUP_H 11 | #define INCLUDE_G35_STRING_GROUP_H 12 | 13 | #include 14 | 15 | // A G35StringGroup takes a set of G35 instances and presents them as a single 16 | // virtual light string of arbitrary length. 17 | // 18 | // A LightProgram that is given a G35StringGroup will then be able to run 19 | // itself over the whole virtual string, without needing to know the details 20 | // of which physical string contains which logical bulb. 21 | class G35StringGroup : public G35 { 22 | public: 23 | G35StringGroup(); 24 | 25 | void AddString(G35* g35); 26 | 27 | virtual uint16_t get_light_count(); 28 | 29 | virtual void set_color(uint8_t bulb, uint8_t intensity, color_t color); 30 | virtual void broadcast_intensity(uint8_t intensity); 31 | 32 | protected: 33 | virtual uint8_t get_broadcast_bulb(); 34 | 35 | private: 36 | enum { MAX_STRINGS = 16 }; 37 | 38 | uint8_t string_count_; 39 | G35* strings_[MAX_STRINGS]; 40 | uint16_t string_offsets_[MAX_STRINGS]; 41 | }; 42 | 43 | #endif // INCLUDE_G35_STRING_GROUP_H 44 | -------------------------------------------------------------------------------- /HalloweenPrograms.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | LightProgram* HalloweenProgramGroup::CreateProgram(G35& lights, 14 | uint8_t program_index) { 15 | switch (program_index % ProgramCount) { 16 | case 0: return new Eyes(lights); 17 | case 1: return new Creepers(lights); 18 | case 2: return new PumpkinChase(lights); 19 | case 3: return new SpookySlow(lights); 20 | case 4: return new SpookyFlicker(lights); 21 | } 22 | 23 | // not reached 24 | return NULL; 25 | } 26 | -------------------------------------------------------------------------------- /HalloweenPrograms.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_HALLOWEEN_PROGRAMS_H 12 | #define INCLUDE_G35_HALLOWEEN_PROGRAMS_H 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | class HalloweenProgramGroup : public LightProgramGroup { 22 | public: 23 | enum { ProgramCount = 5 }; 24 | 25 | virtual LightProgram* CreateProgram(G35& lights, uint8_t program_index); 26 | }; 27 | 28 | #endif // INCLUDE_G35_HALLOWEEN_PROGRAMS_H 29 | -------------------------------------------------------------------------------- /Inchworm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | Inchworm::Inchworm(G35& g35) : LightProgram(g35), count_(0), next_worm_(0) { 14 | g35_.fill_color(0, light_count_, 255, COLOR_BLACK); 15 | } 16 | 17 | uint32_t Inchworm::Do() { 18 | for (int i = 0; i < count_; ++i) { 19 | worms_[i].Do(g35_); 20 | } 21 | if (count_ < 6 && millis() > next_worm_) { 22 | ++count_; 23 | next_worm_ = millis() + 2000 + 1000 * count_; 24 | } 25 | return bulb_frame_; 26 | } 27 | -------------------------------------------------------------------------------- /Inchworm.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_INCHWORM_H 12 | #define INCLUDE_G35_PROGRAMS_INCHWORM_H 13 | 14 | #include 15 | #include 16 | 17 | class Inchworm : public LightProgram { 18 | public: 19 | Inchworm(G35& g35); 20 | uint32_t Do(); 21 | 22 | private: 23 | uint8_t count_; 24 | uint32_t next_worm_; 25 | Worm worms_[6]; 26 | }; 27 | 28 | #endif // INCLUDE_G35_PROGRAMS_INCHWORM_H 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2011 The G35 Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 9 | 2. Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE G35 AUTHORS "AS IS" AND ANY EXPRESS OR 14 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 15 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 16 | EVENT SHALL THE G35 AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 17 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 18 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 20 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 21 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 22 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | 24 | The views and conclusions contained in the software and documentation are 25 | those of the authors and should not be interpreted as representing official 26 | policies, either expressed or implied, of The G35 Authors. 27 | -------------------------------------------------------------------------------- /LightProgram.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_LIGHT_PROGRAMS_H 12 | #define INCLUDE_G35_LIGHT_PROGRAMS_H 13 | 14 | #include 15 | 16 | // Interface for light programs. 17 | // 18 | // A "light program" is what GE means when they say their lights include 14 19 | // programs. An example is "Chasing Red, White, and Blue." 20 | class LightProgram { 21 | public: 22 | LightProgram(G35& g35) 23 | : g35_(g35), light_count_(g35.get_light_count()), 24 | bulb_frame_(g35.get_bulb_frame()) {} 25 | 26 | // Do a single slice of work. Returns the number of milliseconds before 27 | // this function should be called again. 28 | virtual uint32_t Do() = 0; 29 | protected: 30 | G35& g35_; 31 | uint8_t light_count_; 32 | uint8_t bulb_frame_; 33 | }; 34 | 35 | // A collection of LightProgram classes. Putting them here makes it much 36 | // easier on app developers because they don't have to create a switch 37 | // statement for every set of programs they're interested in including. 38 | class LightProgramGroup { 39 | public: 40 | virtual LightProgram* CreateProgram(G35& lights, uint8_t program_index) = 0; 41 | }; 42 | 43 | #endif // INCLUDE_G35_LIGHT_PROGRAMS_H 44 | -------------------------------------------------------------------------------- /MEOPrograms.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 20112 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | Programs referenced in MEOPrograms by Mark Ortiz . 8 | 9 | See README for complete attributions. 10 | */ 11 | 12 | #include 13 | 14 | LightProgram* MEOProgramGroup::CreateProgram(G35& lights, 15 | uint8_t program_index) { 16 | return new Rainbow(lights); 17 | // switch (program_index % ProgramCount) { 18 | // case 0: return new MEOWhites(lights, pattern); 19 | // case 1: return new MEORainbow(lights, pattern); 20 | // case 2: return new MEORandomStrobe(lights, pattern); 21 | // case 3: return new MEOSimplexNoise(lights, pattern); 22 | // case 4: return new MEOSineWave(lights, pattern); 23 | // case 5: return new MEOChasing(lights, pattern); 24 | // case 6: return new MEOColorPhasing(lights, pattern); 25 | // case 7: return new MEODither(lights, pattern); 26 | // case 8: return new MEOOscillate(lights, pattern); 27 | // } 28 | 29 | // not reached 30 | return NULL; 31 | } 32 | -------------------------------------------------------------------------------- /MEOPrograms.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | Programs referenced in MEOPrograms by Mark Ortiz . 8 | 9 | See README for complete attributions. 10 | */ 11 | 12 | #ifndef INCLUDE_G35_MEO_PROGRAMS_H 13 | #define INCLUDE_G35_MEO_PROGRAMS_H 14 | 15 | #include 16 | /* #include */ 17 | /* #include */ 18 | /* #include */ 19 | /* #include */ 20 | #include 21 | /* #include */ 22 | /* #include */ 23 | /* #include */ 24 | /* #include */ 25 | 26 | class MEOProgramGroup : public LightProgramGroup { 27 | public: 28 | enum { ProgramCount = 9 }; 29 | 30 | virtual LightProgram* CreateProgram(G35& lights, uint8_t program_index); 31 | }; 32 | 33 | #endif // INCLUDE_G35_MEO_PROGRAMS_H 34 | -------------------------------------------------------------------------------- /Meteorite.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | Meteorite::Meteorite(G35& g35) 14 | : LightProgram(g35), 15 | position_(g35_.get_last_light() + TAIL) {} 16 | 17 | uint32_t Meteorite::Do() { 18 | if (position_ == static_cast(g35_.get_last_light()) + TAIL) { 19 | position_ = 0; 20 | uint8_t r, g, b; 21 | r = rand() > (RAND_MAX / 2) ? 15 : 0; 22 | g = rand() > (RAND_MAX / 2) ? 15 : 0; 23 | b = rand() > (RAND_MAX / 2) ? 15 : 0; 24 | if (r == 0 && g == 0 && b == 0) { 25 | r = 15; 26 | g = 15; 27 | b = 15; 28 | } 29 | d_ = rand() % bulb_frame_ + 5; 30 | colors_[0] = COLOR(r, g, b); 31 | colors_[1] = COLOR(r * 3 / 4, g * 3 / 4, b * 3 / 4); 32 | colors_[2] = COLOR(r * 2 / 4, g * 2 / 4, b * 2 / 4); 33 | colors_[3] = COLOR(r * 1 / 4, g * 1 / 4, b * 1 / 4); 34 | colors_[4] = COLOR(r * 0 / 4, g * 0 / 4, b * 0 / 4); 35 | } 36 | 37 | for (int i = 0; i < TAIL; ++i) { 38 | int pos = position_ - i; 39 | g35_.set_color_if_in_range(pos, 255, colors_[i]); 40 | } 41 | ++position_; 42 | return d_; 43 | } 44 | -------------------------------------------------------------------------------- /Meteorite.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_METEORITE_H 12 | #define INCLUDE_G35_PROGRAMS_METEORITE_H 13 | 14 | #include 15 | 16 | class Meteorite : public LightProgram { 17 | public: 18 | Meteorite(G35& g35); 19 | uint32_t Do(); 20 | 21 | private: 22 | static const uint8_t TAIL = 5; 23 | 24 | uint8_t d_; 25 | int16_t position_; 26 | color_t colors_[TAIL]; 27 | }; 28 | 29 | #endif // INCLUDE_G35_PROGRAMS_METEORITE_H 30 | -------------------------------------------------------------------------------- /Orbit.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | Orbit::Orbit(G35& g35) 14 | : LightProgram(g35), 15 | should_erase_(true), 16 | count_(MAX_OBJECTS), 17 | light_count_(g35_.get_light_count()) { 18 | set_centers(); 19 | } 20 | 21 | uint32_t Orbit::Do() { 22 | for (int i = 0; i < count_; ++i) { 23 | Orbiter *o = &orbiter_[i]; 24 | o->Do(); 25 | uint8_t x = o->x_local(light_count_, orbiter_center_[i]); 26 | 27 | if (should_erase_ && last_x_[i] != x) { 28 | g35_.set_color(last_x_[i], 255, COLOR_BLACK); 29 | last_x_[i] = x; 30 | } 31 | g35_.set_color(x, 255, o->color()); 32 | } 33 | return bulb_frame_ >> 1; 34 | } 35 | 36 | Orbit::Orbit(G35& g35, bool should_erase) 37 | : LightProgram(g35), 38 | should_erase_(should_erase), 39 | count_(MAX_OBJECTS), 40 | light_count_(g35_.get_light_count()) { 41 | set_centers(); 42 | } 43 | 44 | void Orbit::set_centers() { 45 | for (int i = 0; i < count_; ++i) { 46 | orbiter_center_[i] = rand() % light_count_; 47 | last_x_[i] = 0; 48 | } 49 | } 50 | 51 | OrbitSmudge::OrbitSmudge(G35& g35) : Orbit(g35, false) {} 52 | -------------------------------------------------------------------------------- /Orbit.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_ORBIT_H 12 | #define INCLUDE_G35_PROGRAMS_ORBIT_H 13 | 14 | #include 15 | #include 16 | 17 | class Orbit : public LightProgram { 18 | public: 19 | Orbit(G35& g35); 20 | uint32_t Do(); 21 | 22 | protected: 23 | Orbit(G35& g35, bool should_erase); 24 | 25 | private: 26 | enum { MAX_OBJECTS = 10 }; 27 | bool should_erase_; 28 | uint8_t count_; 29 | int16_t last_light_shifted_; 30 | int8_t light_count_; 31 | Orbiter orbiter_[MAX_OBJECTS]; 32 | uint8_t orbiter_center_[MAX_OBJECTS]; 33 | uint8_t last_x_[MAX_OBJECTS]; 34 | 35 | void set_centers(); 36 | }; 37 | 38 | class OrbitSmudge : public Orbit { 39 | public: 40 | OrbitSmudge(G35& g35); 41 | }; 42 | 43 | #endif // INCLUDE_G35_PROGRAMS_ORBIT_H 44 | -------------------------------------------------------------------------------- /Orbiter.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | Orbiter::Orbiter() 14 | : radius_((float)rand() / (float)RAND_MAX), 15 | angle_(2 * PI * (float)rand() / (float)RAND_MAX), 16 | d_angle_(0), 17 | x_(0), 18 | color_(G35::max_color(rand())) { 19 | const float MIN_ACTION = 0.005; 20 | while (d_angle_ < MIN_ACTION && d_angle_ > -MIN_ACTION) { 21 | d_angle_ = -0.02 + 0.04 * (float)rand() / (float)RAND_MAX; 22 | } 23 | } 24 | 25 | Orbiter::Orbiter(float radius, float d_angle) 26 | : radius_(radius), 27 | angle_(0), 28 | d_angle_(d_angle), 29 | x_(0), 30 | color_(G35::max_color(rand())) {} 31 | 32 | void Orbiter::Do() { 33 | x_ = sin(angle_) * radius_; 34 | angle_ += d_angle_; 35 | } 36 | 37 | float Orbiter::x() { 38 | return x_; 39 | } 40 | 41 | uint8_t Orbiter::x_local(uint8_t range, uint8_t center) { 42 | return ((uint8_t)(x_ * range + center)) % range; 43 | } 44 | 45 | color_t Orbiter::color() { 46 | return color_; 47 | } 48 | -------------------------------------------------------------------------------- /Orbiter.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_ORBITER_H 12 | #define INCLUDE_G35_ORBITER_H 13 | 14 | #include 15 | 16 | // An Orbiter doesn't know about string length. Its coordinate system is 17 | // [0.0, 1.0], and it's the caller's job to scale that to real-world 18 | // values. 19 | class Orbiter { 20 | public: 21 | Orbiter(); 22 | Orbiter(float radius, float d_angle); 23 | void Do(); 24 | float x(); 25 | uint8_t x_local(uint8_t range, uint8_t center); 26 | color_t color(); 27 | 28 | private: 29 | float radius_, angle_, d_angle_; 30 | float x_; 31 | color_t color_; 32 | }; 33 | 34 | #endif // INCLUDE_G35_ORBITER_H 35 | -------------------------------------------------------------------------------- /PlusPrograms.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | LightProgram* PlusProgramGroup::CreateProgram(G35& lights, 14 | uint8_t program_index) { 15 | switch (program_index % ProgramCount) { 16 | case 0: return new Meteorite(lights); 17 | case 1: return new Twinkle(lights); 18 | case 2: return new RedGreenChase(lights); 19 | case 3: return new Pulse(lights); 20 | case 4: return new Orbit(lights); 21 | case 5: return new OrbitSmudge(lights); 22 | case 6: return new Cylon(lights); 23 | case 7: return new Stereo(lights); 24 | case 8: return new Inchworm(lights); 25 | } 26 | 27 | // not reached 28 | return NULL; 29 | } 30 | -------------------------------------------------------------------------------- /PlusPrograms.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PLUS_PROGRAMS_H 12 | #define INCLUDE_G35_PLUS_PROGRAMS_H 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | class PlusProgramGroup : public LightProgramGroup { 25 | public: 26 | enum { ProgramCount = 9 }; 27 | 28 | virtual LightProgram* CreateProgram(G35& lights, uint8_t program_index); 29 | }; 30 | 31 | #endif // INCLUDE_G35_PLUS_PROGRAMS_H 32 | -------------------------------------------------------------------------------- /ProgramRunner.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAM_RUNNER_H 12 | #define INCLUDE_G35_PROGRAM_RUNNER_H 13 | 14 | #include 15 | 16 | // ProgramRunner manages a collection of LightPrograms. 17 | // 18 | // It gives the current program a slice of time to run, decides when it's 19 | // time to switch to the next program, and asks the program_creator callback 20 | // to give it the next program when it's time. In Arduino terms, it's what 21 | // you want to call in your loop() method. 22 | // 23 | // switch_program() is public because the application might sometimes want 24 | // to change programs more frequently, for example if you've implemented 25 | // a remote control receiver. 26 | class ProgramRunner { 27 | public: 28 | ProgramRunner(LightProgram* (*program_creator)(uint8_t program_index), 29 | uint8_t program_count, uint16_t program_duration_seconds) 30 | : program_count_(program_count), 31 | program_duration_seconds_(program_duration_seconds), 32 | program_index_(program_count_ - 1), 33 | next_switch_millis_(0), 34 | program_creator_(program_creator), 35 | program_(NULL), 36 | is_switch_time_based_(true) {} 37 | 38 | // Stops automatic, time-based switching, leaving you to call 39 | // switch_program_to() yourself to switch to specific light programs. Call 40 | // this once during initialization. 41 | void disable_time_based_switching() { 42 | is_switch_time_based_ = false; 43 | } 44 | 45 | // Calls the correct light program as often as needed (e.g., every few 46 | // milliseconds or however long the program defines an animation frame to be). 47 | // You should call this method as often as you can. 48 | void loop() { 49 | uint32_t now = millis(); 50 | if (is_switch_time_based() && now >= next_switch_millis_) { 51 | switch_program(); 52 | } else { 53 | // This is the first loop() with manual switching. We need to have some 54 | // program ready at first, so we'll pick the first one. If you don't want 55 | // this behavior, just call switch_program_to() before your first loop(). 56 | if (program_ == NULL) { 57 | switch_program_to(0); 58 | } 59 | } 60 | if (now >= next_do_millis_) { 61 | next_do_millis_ = now + program_->Do(); 62 | } 63 | } 64 | 65 | // Switches to a specific light program. 66 | void switch_program_to(uint8_t program_index) { 67 | uint32_t now = millis(); 68 | if (is_switch_time_based()) { 69 | next_switch_millis_ = now + (uint32_t)(program_duration_seconds_) * 1000; 70 | } 71 | next_do_millis_ = now; 72 | if (program_ != NULL) { 73 | delete program_; 74 | } 75 | program_index_ = program_index; 76 | program_ = program_creator_(program_index_); 77 | } 78 | 79 | // Switches to the next light program according to the program_creator 80 | // method. 81 | void switch_program() { 82 | switch_program_to(++program_index_); 83 | if (program_index_ == program_count_) { 84 | program_index_ = 0; 85 | } 86 | } 87 | 88 | private: 89 | bool is_switch_time_based() { return is_switch_time_based_; } 90 | 91 | uint8_t program_count_; 92 | uint16_t program_duration_seconds_; 93 | uint8_t program_index_; 94 | uint32_t next_switch_millis_; 95 | uint32_t next_do_millis_; 96 | LightProgram* (*program_creator_)(uint8_t program_index); 97 | LightProgram* program_; 98 | bool is_switch_time_based_; 99 | }; 100 | 101 | #endif // INCLUDE_G35_PROGRAM_RUNNER_H 102 | -------------------------------------------------------------------------------- /Pulse.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | Pulse::Pulse(G35& g35) 14 | : LightProgram(g35), 15 | count_(1), 16 | sequence_(0) {} 17 | 18 | uint32_t Pulse::Do() { 19 | g35_.fill_sequence(0, count_, sequence_, 1, pulser); 20 | if (count_ < light_count_) { 21 | ++count_; 22 | } else { 23 | ++sequence_; 24 | } 25 | return 1; 26 | } 27 | 28 | // static 29 | bool Pulse::pulser(uint16_t sequence, color_t& color, uint8_t& intensity) { 30 | const int PHASE = 32; 31 | const int PULSE_RATE = 2; // Above 1 is glitchy but IMO more attractive. 32 | color = G35::max_color((sequence + PHASE) / (PHASE * 2)); 33 | intensity = abs(PHASE - (int)(sequence * PULSE_RATE) % (PHASE + PHASE)); 34 | return true; 35 | } 36 | -------------------------------------------------------------------------------- /Pulse.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_PULSE_H 12 | #define INCLUDE_G35_PROGRAMS_PULSE_H 13 | 14 | #include 15 | 16 | class Pulse : public LightProgram { 17 | public: 18 | Pulse(G35& g35); 19 | uint32_t Do(); 20 | 21 | private: 22 | uint8_t count_; 23 | uint16_t sequence_; 24 | 25 | static bool pulser(uint16_t sequence, color_t& color, uint8_t& intensity); 26 | }; 27 | 28 | #endif // INCLUDE_G35_PROGRAMS_PULSE_H 29 | -------------------------------------------------------------------------------- /PumpkinChase.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | PumpkinChase::PumpkinChase(G35& g35) 14 | : LightProgram(g35), 15 | count_(1), 16 | sequence_(0) {} 17 | 18 | uint32_t PumpkinChase::Do() { 19 | g35_.fill_sequence(0, count_, sequence_, 5, 255, orange_green); 20 | if (count_ < light_count_) { 21 | ++count_; 22 | } else { 23 | ++sequence_; 24 | } 25 | return bulb_frame_; 26 | } 27 | 28 | // static 29 | color_t PumpkinChase::orange_green(uint16_t sequence) { 30 | uint16_t s = sequence % 9; 31 | if (s == 3) { 32 | return COLOR_ORANGE; 33 | } 34 | if (s == 6) { 35 | return COLOR_GREEN; 36 | } 37 | return COLOR_BLACK; 38 | } 39 | -------------------------------------------------------------------------------- /PumpkinChase.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_PUMPKIN_CHASE_H 12 | #define INCLUDE_G35_PROGRAMS_PUMPKIN_CHASE_H 13 | 14 | #include 15 | 16 | class PumpkinChase : public LightProgram { 17 | public: 18 | PumpkinChase(G35& g35); 19 | uint32_t Do(); 20 | static color_t orange_green(uint16_t sequence); 21 | 22 | private: 23 | uint8_t count_; 24 | uint16_t sequence_; 25 | }; 26 | 27 | #endif // INCLUDE_G35_PROGRAMS_PUMPKIN_CHASE_H 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | ![G-35 Lights, Green](/images/green_lights.jpg?raw=true "G-35 Lights") Read 5 | [the blog post](http://www.deepdarc.com/2010/11/27/hacking-christmas-lights/) 6 | that started it all. 7 | 8 | This library makes it easy to replace the controller in GE Color Effects 9 | Christmas lights with an Arduino, and to run much better light programs. If you 10 | can program C or Processing, it's pretty easy to make new programs, too! 11 | 12 | See a [demo](http://www.youtube.com/watch?v=QyKt7tHV-EM). There is also a 13 | [not-awful professional demo](http://www.geholidaylighting.com/holiday-lighting/led/color-effects) 14 | of the original, unmodified hardware. 15 | 16 | Features 17 | ======== 18 | 19 | - With your Arduino, Teensy, or pile of laundry lint that happens to contain an 20 | Atmel AVR ATmega, G35Arduino becomes a splice-in replacement for the stock G35 21 | controller. Contains versions of the same programs that ship with the lights. 22 | Your spouse won't know the difference! 23 | 24 | - Also contains custom programs: Inchworm, Orbit, Cylon, Meteorite, just to name 25 | a few! Your spouse will know the difference! 26 | 27 | - Easy to add your own programs. If you can make it through the Arduino Blink 28 | tutorial, you can probably write your own light program! 29 | 30 | - Synchronizes multiple strings. Have them each run individual instances of the 31 | same light program. Have them each run different programs, but with 32 | synchronized program changes. Or combine as many strings as you want into a 33 | single mondo gigantic virtual string! (Number of physical strings is limited 34 | by the number of output pins on your microcontroller, as well as the memory 35 | requirements of the running light programs.) 36 | 37 | - Express your individualism! G35Arduino operates completely independently of 38 | [requests from Twitter](http://www.cheerlights.com/), Facebook, SMS, XBee, 39 | neighbors, and drive-thru spectators. You bought 'em, you should get to 40 | control what they do! 41 | 42 | Requirements 43 | ============ 44 | 45 | - [Arduino 1.6 SDK](http://arduino.cc/en/Main/Software). Earlier versions will 46 | work, but installation is tedious. 47 | 48 | - Any of the following: an Arduino or Arduino-compatible, a 49 | [Teensy](http://www.pjrc.com/) with Teensyduino or else flashed with an 50 | Arduino Leonardo bootloader. Also a plain Atmel ATmega of some sort, if you 51 | know what you're doing. 52 | 53 | - At least one working strand of GE G-35 Color Effects Christmas lights that you 54 | are willing to slice up and solder back together again. 55 | 56 | Installation 57 | ============ 58 | 59 | 1. Download this project from GitHub as a ZIP file. 60 | 61 | 1. In your Arduino IDE, look for Sketch → Include Library → Add ZIP 62 | Library …, then select the ZIP file you just downloaded. 63 | 64 | 1. Look for the new G35Arduino submenu in your Examples menu. 65 | 66 | 1. Upload the BasicExample sketch to your Arduino. You should see the pin-13 LED 67 | flicker as the sketch tries to send data to your lights. 68 | 69 | 1. Chop off the stock controller on your lights, being careful to note the 70 | function of the three leads from the first light (from left to right looking 71 | at the first light pointing upward, they're V+, DATA, and GND). 72 | 73 | 1. Put V+ on the Arduino 5V pin, GND on the GND pin, and DATA on pin 13, and 74 | your lights should come back to life! 75 | 76 | I've been happily running two strands on my house directly off the Arduino 77 | (i.e., not using the stock power transformer) with an old USB power supply rated 78 | 5V/1A from a Kodak Zi8. Your mileage may vary. 79 | 80 | Contributing 81 | ============ 82 | 83 | Source-code contributions are welcome. If you think you might contribute 84 | improvements back to the project, git clone into libraries/ instead of 85 | unzipping, and to avoid going insane, check the "external editor" option in the 86 | Arduino IDE and use a text editor directly on the library source. 87 | 88 | We try to follow Google's C++ coding standards: 2 spaces, no tabs, 80 columns, 89 | and follow the existing naming/capitalization conventions in the code. 90 | 91 | Further Reading 92 | === 93 | 94 | - There's a fork of this project that I've heard puts my programs to shame. 95 | [Check it out](https://github.com/MarkEMarkEMark/G35-MEO-Programs). 96 | 97 | - Want to hack on the original G35 remote with your Arduino? 98 | [There's a library for that](https://lukecyca.com/2013/g35-rf-remote.html). 99 | 100 | Credits 101 | ======= 102 | 103 | - [Paul Martis](http://www.digitalmisery.com) 104 | 105 | - [Robert Quattlebaum](http://www.deepdarc.com/2010/11/27/hacking-christmas-lights) 106 | 107 | - [Scott Harris](http://scottrharris.blogspot.com/2010/12/controlling-ge-color-effects-lights.html) 108 | 109 | - [Mark Ortiz](https://github.com/MarkEMarkEMark), with some of Mark's code 110 | inspired by [Adafruit](http://adafruit.com/) 111 | 112 | - [Mike Tsao](http://github.com/sowbug) 113 | -------------------------------------------------------------------------------- /Rainbow.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | Programs referenced in MEOPrograms by Mark Ortiz . 8 | Portions adapted from Adafruit. 9 | 10 | See README for complete attributions. 11 | */ 12 | 13 | #include 14 | 15 | #define PATTERN_COUNT (8) 16 | Rainbow::Rainbow(G35& g35) 17 | : LightProgram(g35), wait_(0), pattern_(rand() % PATTERN_COUNT), step_(0) { 18 | } 19 | 20 | uint32_t Rainbow::Do() { 21 | bool fortyEight; 22 | for (int i=0; i < light_count_; i++) { 23 | switch (pattern_) { 24 | case 0: 25 | fortyEight = false; 26 | g35_.fill_color(i, 1, G35::MAX_INTENSITY, 27 | Rainbow::LineRG((i + step_) % 32)); 28 | break; 29 | case 1: 30 | fortyEight = false; 31 | g35_.fill_color(i, 1, G35::MAX_INTENSITY, 32 | Rainbow::LineGB((i + step_) % 32)); 33 | break; 34 | case 2: 35 | fortyEight = false; 36 | g35_.fill_color(i, 1, G35::MAX_INTENSITY, 37 | Rainbow::LineBR((i + step_) % 32)); 38 | break; 39 | case 3: 40 | fortyEight = true; 41 | g35_.fill_color(i, 1, G35::MAX_INTENSITY, 42 | Rainbow::Wheel((i + step_) % 48)); 43 | break; 44 | case 4: 45 | fortyEight = false; 46 | g35_.fill_color(i, 1, G35::MAX_INTENSITY, 47 | Rainbow::LineRG(((i * 32 / light_count_) + step_) % 32)); 48 | break; 49 | case 5: 50 | fortyEight = false; 51 | g35_.fill_color(i, 1, G35::MAX_INTENSITY, 52 | Rainbow::LineGB(((i * 32 / light_count_) + step_) % 32)); 53 | break; 54 | case 6: 55 | fortyEight = false; 56 | g35_.fill_color(i, 1, G35::MAX_INTENSITY, 57 | Rainbow::LineBR(((i * 32 / light_count_) + step_) % 32)); 58 | break; 59 | case 7: 60 | fortyEight = true; 61 | g35_.fill_color(i, 1, G35::MAX_INTENSITY, 62 | Rainbow::Wheel(((i * 48 / light_count_) + step_) % 48)); 63 | break; 64 | } 65 | } 66 | 67 | // reset at end of wheel or line 68 | ++step_; 69 | if (((step_ == 48) && fortyEight) || ((step_ == 32) && !fortyEight)) { 70 | step_ = 0; 71 | } 72 | 73 | delay(wait_); 74 | 75 | return bulb_frame_; 76 | } 77 | 78 | uint32_t Rainbow::Wheel(uint16_t WheelPos) { 79 | byte r, g, b; 80 | switch (WheelPos / 16) { 81 | case 0: 82 | r = 15 - WheelPos % 16; // red down 83 | g = WheelPos % 16; // green up 84 | b = 0; // blue off 85 | break; 86 | case 1: 87 | g = 15 - WheelPos % 16; // green down 88 | b = WheelPos % 16; // blue up 89 | r = 0; // red off 90 | break; 91 | case 2: 92 | b = 15 - WheelPos % 16; // blue down 93 | r = WheelPos % 16; // red up 94 | g = 0; // green off 95 | break; 96 | } 97 | return (COLOR(r,g,b)); 98 | } 99 | 100 | uint32_t Rainbow::LineRG(uint16_t WheelPos) { 101 | byte r, g, b; 102 | switch (WheelPos / 16) { 103 | case 0: 104 | r = 15 - WheelPos % 16; // red down 105 | g = WheelPos % 16; // green up 106 | b = 0; // blue off 107 | break; 108 | case 1: 109 | r = WheelPos % 16; // red up 110 | g = 15 - WheelPos % 16; // green down 111 | b = 0; // blue off 112 | break; 113 | } 114 | return (COLOR(r,g,b)); 115 | } 116 | 117 | uint32_t Rainbow::LineGB(uint16_t WheelPos) { 118 | byte r, g, b; 119 | switch (WheelPos / 16) { 120 | case 0: 121 | r = 0; // red off 122 | g = 15 - WheelPos % 16; // green down 123 | b = WheelPos % 16; // blue up 124 | break; 125 | case 1: 126 | r = 0; // red off 127 | g = WheelPos % 16; // green up 128 | b = 15 - WheelPos % 16; // blue down 129 | break; 130 | } 131 | return (COLOR(r,g,b)); 132 | } 133 | 134 | uint32_t Rainbow::LineBR(uint16_t WheelPos) { 135 | byte r, g, b; 136 | switch (WheelPos / 16) { 137 | case 0: 138 | r = WheelPos % 16; // red up 139 | g = 0; // green off 140 | b = 15 - WheelPos % 16; // blue down 141 | break; 142 | case 1: 143 | r = 15 - WheelPos % 16; // red down 144 | g = 0; // green off 145 | b = WheelPos % 16; // blue up 146 | break; 147 | } 148 | return (COLOR(r,g,b)); 149 | } 150 | -------------------------------------------------------------------------------- /Rainbow.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | Programs referenced in MEOPrograms by Mark Ortiz . 8 | Portions adapted from Adafruit. 9 | 10 | See README for complete attributions. 11 | */ 12 | 13 | #ifndef INCLUDE_G35_PROGRAMS_RAINBOW_H 14 | #define INCLUDE_G35_PROGRAMS_RAINBOW_H 15 | 16 | #include 17 | 18 | class Rainbow : public LightProgram { 19 | public: 20 | Rainbow(G35& g35); 21 | uint32_t Do(); 22 | 23 | private: 24 | uint32_t Wheel(uint16_t WheelPos); 25 | uint32_t LineRG(uint16_t WheelPos); 26 | uint32_t LineGB(uint16_t WheelPos); 27 | uint32_t LineBR(uint16_t WheelPos); 28 | 29 | uint8_t wait_; 30 | uint8_t pattern_; 31 | uint8_t step_; 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /RedGreenChase.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | RedGreenChase::RedGreenChase(G35& g35) 14 | : LightProgram(g35), 15 | count_(1), 16 | sequence_(0) {} 17 | 18 | uint32_t RedGreenChase::Do() { 19 | g35_.fill_sequence(0, count_, sequence_, 5, 255, red_green); 20 | if (count_ < light_count_) { 21 | ++count_; 22 | } else { 23 | ++sequence_; 24 | } 25 | return bulb_frame_; 26 | } 27 | 28 | // static 29 | color_t RedGreenChase::red_green(uint16_t sequence) { 30 | return sequence % 2 ? COLOR_RED : COLOR_GREEN; 31 | } 32 | -------------------------------------------------------------------------------- /RedGreenChase.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_RED_GREEN_CHASE_H 12 | #define INCLUDE_G35_PROGRAMS_RED_GREEN_CHASE_H 13 | 14 | #include 15 | 16 | class RedGreenChase : public LightProgram { 17 | public: 18 | RedGreenChase(G35& g35); 19 | uint32_t Do(); 20 | static color_t red_green(uint16_t sequence); 21 | 22 | private: 23 | uint8_t count_; 24 | uint16_t sequence_; 25 | }; 26 | 27 | #endif // INCLUDE_G35_PROGRAMS_RED_GREEN_CHASE_H 28 | -------------------------------------------------------------------------------- /SpookyFlicker.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | SpookyFlicker::SpookyFlicker(G35& g35) : LightProgram(g35) { 14 | intensities_ = static_cast(malloc(light_count_ * sizeof(uint8_t))); 15 | deltas_ = static_cast(malloc(light_count_ * sizeof(int8_t))); 16 | for (uint8_t i = 0; i < light_count_; ++i) { 17 | intensities_[i] = rand(); 18 | deltas_[i] = rand() % 5 - 2; 19 | } 20 | g35_.fill_color(0, light_count_, 255, COLOR_BLACK); 21 | } 22 | 23 | SpookyFlicker::~SpookyFlicker() { 24 | free(intensities_); 25 | free(deltas_); 26 | } 27 | 28 | uint32_t SpookyFlicker::Do() { 29 | for (int i = 0; i < light_count_; ++i) { 30 | g35_.set_color(i, intensities_[i], COLOR_ORANGE); 31 | intensities_[i] += deltas_[i]; 32 | } 33 | return 10; 34 | } 35 | -------------------------------------------------------------------------------- /SpookyFlicker.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_SPOOKY_FLICKER_H 12 | #define INCLUDE_G35_PROGRAMS_SPOOKY_FLICKER_H 13 | 14 | #include 15 | 16 | class SpookyFlicker : public LightProgram { 17 | public: 18 | SpookyFlicker(G35& g35); 19 | ~SpookyFlicker(); 20 | 21 | uint32_t Do(); 22 | 23 | private: 24 | uint8_t *intensities_; 25 | int8_t *deltas_; 26 | }; 27 | 28 | #endif // INCLUDE_G35_PROGRAMS_SPOOKY_FLICKER_H 29 | -------------------------------------------------------------------------------- /SpookySlow.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | SpookySlow::SpookySlow(G35& g35) : LightProgram(g35), remaining_(0) { 14 | } 15 | 16 | uint32_t SpookySlow::Do() { 17 | if (remaining_ == 0) { 18 | remaining_ = rand() % (light_count_ >> 3); 19 | g35_.fill_color(0, light_count_, 255, COLOR_BLACK); 20 | } 21 | if (remaining_-- > 2) { 22 | g35_.set_color(rand() % light_count_, G35::MAX_INTENSITY, 23 | (rand() & 1) ? COLOR_ORANGE : COLOR_PALE_ORANGE); 24 | } 25 | return 1000; 26 | } 27 | -------------------------------------------------------------------------------- /SpookySlow.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_SPOOKY_SLOW_H 12 | #define INCLUDE_G35_PROGRAMS_SPOOKY_SLOW_H 13 | 14 | #include 15 | 16 | class SpookySlow : public LightProgram { 17 | public: 18 | SpookySlow(G35& g35); 19 | uint32_t Do(); 20 | 21 | private: 22 | uint16_t remaining_; 23 | }; 24 | 25 | #endif // INCLUDE_G35_PROGRAMS_SPOOKY_SLOW_H 26 | -------------------------------------------------------------------------------- /Stereo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | Stereo::Stereo(G35& g35) : LightProgram(g35), 14 | light_count_(g35_.get_light_count()), 15 | half_light_count_((float)light_count_ / 2.0), 16 | level0_(half_light_count_ * 0.5), 17 | level1_(half_light_count_ * 0.1666), 18 | level2_(half_light_count_ * 0.1666), 19 | level3_(half_light_count_ * 0.1666), 20 | step_(0), peak_(0) { 21 | g35_.fill_color(0, light_count_, 255, COLOR_BLACK); 22 | } 23 | 24 | uint32_t Stereo::Do() { 25 | float wave = level0_ + 26 | sin(step_) * level1_ + 27 | sin(step_ * .7) * level2_ + 28 | sin(step_ * .3) * level3_; 29 | if (wave > peak_) { 30 | peak_ = wave; 31 | } else { 32 | peak_ *= 0.99; 33 | } 34 | uint8_t i = wave; 35 | while (i--) { 36 | g35_.set_color(i, 255, COLOR_GREEN); 37 | g35_.set_color(light_count_ - i, 255, COLOR_GREEN); 38 | } 39 | uint8_t halfway = g35_.get_halfway_point(); 40 | uint8_t peak_i = peak_; 41 | for (i = wave; i < halfway; ++i) { 42 | uint8_t color = i == peak_i ? COLOR_RED : COLOR_BLACK; 43 | g35_.set_color(i, 255, color); 44 | g35_.set_color(light_count_ - i, 255, color); 45 | } 46 | step_ += 0.4; 47 | return bulb_frame_; 48 | } 49 | -------------------------------------------------------------------------------- /Stereo.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_STEREO_H 12 | #define INCLUDE_G35_PROGRAMS_STEREO_H 13 | 14 | #include 15 | 16 | // Stereo was inspired by SparkFun's "FAKE MUSIC!" demo for their 17 | // Bargraph Breakout board. Thanks, guys! 18 | class Stereo : public LightProgram { 19 | public: 20 | Stereo(G35& g35); 21 | uint32_t Do(); 22 | 23 | private: 24 | const uint8_t light_count_; 25 | const float half_light_count_; 26 | const float level0_, level1_, level2_, level3_; 27 | float step_, peak_; 28 | }; 29 | 30 | #endif // INCLUDE_G35_PROGRAMS_STEREO_H 31 | -------------------------------------------------------------------------------- /StockPrograms.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | SteadyWhite::SteadyWhite(G35& g35) 14 | : LightProgram(g35), intensity_(0) { 15 | g35_.fill_color(0, light_count_, 0, COLOR_WHITE); 16 | } 17 | 18 | uint32_t SteadyWhite::Do() { 19 | if (intensity_ <= G35::MAX_INTENSITY) { 20 | g35_.broadcast_intensity(intensity_++); 21 | return bulb_frame_; 22 | } 23 | return 1000; 24 | } 25 | 26 | CrossOverWave::CrossOverWave(G35& g35) 27 | : LightProgram(g35), x_(light_count_) {} 28 | 29 | uint32_t CrossOverWave::Do() { 30 | if (x_ == light_count_) { 31 | x_ = 0; 32 | color_a_ = 0; 33 | color_b_ = 0; 34 | while (color_a_ == color_b_) { 35 | color_a_ = G35::max_color(rand()); 36 | color_b_ = G35::max_color(rand()); 37 | } 38 | } 39 | g35_.set_color(x_, G35::MAX_INTENSITY, color_a_); 40 | g35_.set_color(g35_.get_last_light() - x_, G35::MAX_INTENSITY, color_b_); 41 | ++x_; 42 | return bulb_frame_; 43 | } 44 | 45 | ForwardWave::ForwardWave(G35& g35) 46 | : LightProgram(g35), x_(light_count_) {} 47 | 48 | uint32_t ForwardWave::Do() { 49 | if (x_ == light_count_) { 50 | x_ = 0; 51 | color_t old_color = color_; 52 | do { 53 | color_ = G35::max_color(rand()); 54 | } while (old_color == color_); 55 | } 56 | g35_.set_color(x_, G35::MAX_INTENSITY, color_); 57 | ++x_; 58 | return bulb_frame_; 59 | } 60 | 61 | ChasingRainbow::ChasingRainbow(G35& g35) 62 | : LightProgram(g35), count_(1), sequence_(0) {} 63 | 64 | uint32_t ChasingRainbow::Do() { 65 | g35_.fill_sequence(0, count_, sequence_, 1, G35::MAX_INTENSITY, 66 | G35::rainbow_color); 67 | if (count_ < light_count_) { 68 | ++count_; 69 | } else { 70 | ++sequence_; 71 | } 72 | return bulb_frame_; 73 | } 74 | 75 | AlternateDirectionalWave::AlternateDirectionalWave(G35& g35) 76 | : LightProgram(g35), x_(0), x_target_(light_count_), 77 | x_other_target_(-1), direction_(1), color_(G35::max_color(rand())) {} 78 | 79 | uint32_t AlternateDirectionalWave::Do() { 80 | g35_.set_color(x_, G35::MAX_INTENSITY, color_); 81 | x_ += direction_; 82 | 83 | if (x_ == x_target_) { 84 | direction_ = -direction_; 85 | x_ += direction_; 86 | int16_t t = x_target_; 87 | x_target_ = x_other_target_; 88 | x_other_target_ = t; 89 | color_t old_color = color_; 90 | do { 91 | color_ = G35::max_color(rand()); 92 | } while (old_color == color_); 93 | return 1000; 94 | } 95 | return bulb_frame_; 96 | } 97 | 98 | FadeInFadeOutSolidColors::FadeInFadeOutSolidColors(G35& g35) 99 | : LightProgram(g35), color_(0), intensity_(0) {} 100 | 101 | uint32_t FadeInFadeOutSolidColors::Do() { 102 | if (intensity_ == 0) { 103 | color_t new_color = color_; 104 | do { 105 | color_ = G35::max_color(rand()); 106 | } while (new_color == color_); 107 | 108 | g35_.broadcast_intensity(0); 109 | g35_.fill_color(0, light_count_, 0, color_); 110 | d_intensity_ = 1; 111 | } 112 | if (intensity_ == G35::MAX_INTENSITY) { 113 | d_intensity_ = -1; 114 | } 115 | intensity_ += d_intensity_; 116 | g35_.broadcast_intensity(intensity_); 117 | 118 | return 10; 119 | } 120 | 121 | BidirectionalWave::BidirectionalWave(G35& g35) 122 | : LightProgram(g35), x_(g35_.get_halfway_point()) {} 123 | 124 | uint32_t BidirectionalWave::Do() { 125 | // With 50 lights, we run into some edge cases because 50 isn't evenly 126 | // divisible by 4. It's a fairly crazy program to start with, so I'm 127 | // leaving it like this. 128 | if (x_ == g35_.get_halfway_point()) { 129 | x_ = 0; 130 | do { 131 | color_a_ = G35::max_color(rand()); 132 | color_b_ = G35::max_color(rand()); 133 | } while (color_a_ == color_b_); 134 | do { 135 | color_c_ = G35::max_color(rand()); 136 | color_d_ = G35::max_color(rand()); 137 | } while (color_c_ == color_d_); 138 | } 139 | g35_.set_color(x_, G35::MAX_INTENSITY, color_a_); 140 | g35_.set_color(g35_.get_halfway_point() - 1 - x_, G35::MAX_INTENSITY, 141 | color_b_); 142 | g35_.set_color(g35_.get_halfway_point() + x_, G35::MAX_INTENSITY, 143 | color_c_); 144 | g35_.set_color(g35_.get_last_light() - x_, G35::MAX_INTENSITY, color_d_); 145 | ++x_; 146 | return bulb_frame_; 147 | } 148 | 149 | ChasingSolidColors::ChasingSolidColors(G35& g35) 150 | : LightProgram(g35), count_(1), sequence_(0) {} 151 | 152 | uint32_t ChasingSolidColors::Do() { 153 | g35_.fill_sequence(0, count_, sequence_, 5, G35::MAX_INTENSITY, 154 | G35::max_color); 155 | if (count_ < light_count_) { 156 | ++count_; 157 | } else { 158 | ++sequence_; 159 | } 160 | return bulb_frame_; 161 | } 162 | 163 | FadeInFadeOutMultiColors::FadeInFadeOutMultiColors(G35& g35) 164 | : LightProgram(g35), state_(0), intensity_(0) {} 165 | 166 | uint32_t FadeInFadeOutMultiColors::Do() { 167 | switch (state_) { 168 | case 0: 169 | if (intensity_++ == 0) { 170 | // We mask off the last two bits so that the color segments are aligned 171 | // from scene to scene. 172 | g35_.fill_sequence(rand() & 0x7ffc, 4, 0, G35::max_color); 173 | } 174 | if (intensity_ == G35::MAX_INTENSITY) { 175 | state_ = 1; 176 | } 177 | break; 178 | case 1: 179 | if (--intensity_ == 0) { 180 | state_ = 0; 181 | } 182 | break; 183 | } 184 | g35_.broadcast_intensity(intensity_); 185 | 186 | return 10; 187 | } 188 | 189 | ChasingTwoColors::ChasingTwoColors(G35& g35) 190 | : LightProgram(g35), sequence_(0) {} 191 | 192 | uint32_t ChasingTwoColors::Do() { 193 | g35_.fill_sequence(sequence_, light_count_ / 2, 194 | G35::MAX_INTENSITY, G35::rainbow_color); 195 | sequence_ += light_count_ / 2; 196 | return 500; 197 | } 198 | 199 | RandomSparkling::RandomSparkling(G35& g35) 200 | : LightProgram(g35), state_(1) {} 201 | 202 | uint32_t RandomSparkling::Do() { 203 | if (state_++ > 1) { 204 | state_ = 0; 205 | } 206 | if (state_ == 0) { 207 | g35_.fill_random_max(0, light_count_, G35::MAX_INTENSITY); 208 | return 1000; 209 | } 210 | g35_.fill_color(0, light_count_, G35::MAX_INTENSITY, COLOR_BLACK); 211 | return 500; 212 | } 213 | 214 | ChasingMultiColors::ChasingMultiColors(G35& g35) 215 | : LightProgram(g35), count_(1), sequence_(0) {} 216 | 217 | uint32_t ChasingMultiColors::Do() { 218 | g35_.fill_sequence(0, count_, sequence_, 1, G35::MAX_INTENSITY, 219 | G35::max_color); 220 | if (count_ < light_count_) { 221 | ++count_; 222 | } else { 223 | ++sequence_; 224 | } 225 | return bulb_frame_ * 6; 226 | } 227 | 228 | ChasingWhiteRedBlue::ChasingWhiteRedBlue(G35& g35) 229 | : LightProgram(g35), count_(1), sequence_(0) {} 230 | 231 | uint32_t ChasingWhiteRedBlue::Do() { 232 | g35_.fill_sequence(0, count_, sequence_, 3, G35::MAX_INTENSITY, 233 | red_white_blue); 234 | if (count_ < light_count_) { 235 | ++count_; 236 | } else { 237 | ++sequence_; 238 | } 239 | return bulb_frame_; 240 | } 241 | 242 | // static 243 | color_t ChasingWhiteRedBlue::red_white_blue(uint16_t sequence) { 244 | sequence = sequence % 3; 245 | if (sequence == 0) { 246 | return COLOR_RED; 247 | } 248 | if (sequence == 1) { 249 | return COLOR_WHITE; 250 | } 251 | return COLOR_BLUE; 252 | } 253 | 254 | LightProgram* StockProgramGroup::CreateProgram(G35& lights, 255 | uint8_t program_index) { 256 | switch (program_index % ProgramCount) { 257 | case 0: return new CrossOverWave(lights); 258 | case 1: return new ForwardWave(lights); 259 | case 2: return new ChasingRainbow(lights); 260 | case 3: return new AlternateDirectionalWave(lights); 261 | case 4: return new FadeInFadeOutSolidColors(lights); 262 | case 5: return new BidirectionalWave(lights); 263 | case 6: return new ChasingSolidColors(lights); 264 | case 7: return new FadeInFadeOutMultiColors(lights); 265 | case 8: return new ChasingTwoColors(lights); 266 | case 9: return new RandomSparkling(lights); 267 | case 10: return new ChasingMultiColors(lights); 268 | case 11: return new ChasingWhiteRedBlue(lights); 269 | } 270 | 271 | // not reached 272 | return NULL; 273 | } 274 | -------------------------------------------------------------------------------- /StockPrograms.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_STOCK_PROGRAMS_H 12 | #define INCLUDE_G35_STOCK_PROGRAMS_H 13 | 14 | #include 15 | 16 | // We don't count SteadyWhite because it's more of a mode than a program. 17 | #define STOCK_PROGRAM_COUNT (12) 18 | 19 | class SteadyWhite : public LightProgram { 20 | public: 21 | SteadyWhite(G35& g35); 22 | uint32_t Do(); 23 | 24 | private: 25 | uint8_t intensity_; 26 | }; 27 | 28 | class CrossOverWave : public LightProgram { 29 | public: 30 | CrossOverWave(G35& g35); 31 | uint32_t Do(); 32 | 33 | private: 34 | uint8_t x_; 35 | color_t color_a_; 36 | color_t color_b_; 37 | }; 38 | 39 | class ForwardWave : public LightProgram { 40 | public: 41 | ForwardWave(G35& g35); 42 | uint32_t Do(); 43 | 44 | private: 45 | uint8_t x_; 46 | color_t color_; 47 | }; 48 | 49 | class ChasingRainbow : public LightProgram { 50 | public: 51 | ChasingRainbow(G35& g35); 52 | uint32_t Do(); 53 | 54 | private: 55 | uint8_t count_; 56 | uint16_t sequence_; 57 | }; 58 | 59 | class AlternateDirectionalWave : public LightProgram { 60 | public: 61 | AlternateDirectionalWave(G35& g35); 62 | uint32_t Do(); 63 | 64 | private: 65 | int16_t x_; 66 | int16_t x_target_; 67 | int16_t x_other_target_; 68 | int8_t direction_; 69 | color_t color_; 70 | }; 71 | 72 | class FadeInFadeOutSolidColors : public LightProgram { 73 | public: 74 | FadeInFadeOutSolidColors(G35& g35); 75 | uint32_t Do(); 76 | 77 | private: 78 | color_t color_; 79 | uint8_t intensity_; 80 | int8_t d_intensity_; 81 | }; 82 | 83 | class BidirectionalWave : public LightProgram { 84 | public: 85 | BidirectionalWave(G35& g35); 86 | uint32_t Do(); 87 | 88 | private: 89 | uint8_t x_; 90 | color_t color_a_; 91 | color_t color_b_; 92 | color_t color_c_; 93 | color_t color_d_; 94 | }; 95 | 96 | class ChasingSolidColors : public LightProgram { 97 | public: 98 | ChasingSolidColors(G35& g35); 99 | uint32_t Do(); 100 | 101 | private: 102 | uint8_t count_; 103 | uint16_t sequence_; 104 | }; 105 | 106 | class FadeInFadeOutMultiColors : public LightProgram { 107 | public: 108 | FadeInFadeOutMultiColors(G35& g35); 109 | uint32_t Do(); 110 | 111 | private: 112 | uint8_t state_; 113 | uint8_t intensity_; 114 | }; 115 | 116 | class ChasingTwoColors : public LightProgram { 117 | public: 118 | ChasingTwoColors(G35& g35); 119 | uint32_t Do(); 120 | 121 | private: 122 | uint16_t sequence_; 123 | }; 124 | 125 | class RandomSparkling : public LightProgram { 126 | public: 127 | RandomSparkling(G35& g35); 128 | uint32_t Do(); 129 | 130 | private: 131 | color_t color_; 132 | uint8_t state_; 133 | }; 134 | 135 | class ChasingMultiColors : public LightProgram { 136 | public: 137 | ChasingMultiColors(G35& g35); 138 | uint32_t Do(); 139 | 140 | private: 141 | uint8_t count_; 142 | uint16_t sequence_; 143 | }; 144 | 145 | class ChasingWhiteRedBlue : public LightProgram { 146 | public: 147 | ChasingWhiteRedBlue(G35& g35); 148 | uint32_t Do(); 149 | static color_t red_white_blue(uint16_t sequence); 150 | 151 | private: 152 | uint8_t count_; 153 | uint16_t sequence_; 154 | }; 155 | 156 | class StockProgramGroup : public LightProgramGroup { 157 | public: 158 | enum { ProgramCount = 12 }; 159 | 160 | virtual LightProgram* CreateProgram(G35& lights, uint8_t program_index); 161 | }; 162 | 163 | #endif // INCLUDE_G35_STOCK_PROGRAMS_H 164 | -------------------------------------------------------------------------------- /Twinkle.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | Twinkle::Twinkle(G35& g35) : LightProgram(g35) { 14 | g35_.fill_random_max(0, light_count_, G35::MAX_INTENSITY); 15 | } 16 | 17 | uint32_t Twinkle::Do() { 18 | g35_.set_color(rand() % light_count_, G35::MAX_INTENSITY, 19 | G35::max_color(rand())); 20 | return bulb_frame_; 21 | } 22 | -------------------------------------------------------------------------------- /Twinkle.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_TWINKLE_H 12 | #define INCLUDE_G35_PROGRAMS_TWINKLE_H 13 | 14 | #include 15 | 16 | class Twinkle : public LightProgram { 17 | public: 18 | Twinkle(G35& g35); 19 | uint32_t Do(); 20 | }; 21 | 22 | #endif // INCLUDE_G35_PROGRAMS_TWINKLE_H 23 | -------------------------------------------------------------------------------- /ValentinesDay.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define NUM_LEDS 50 4 | #define DATA_PIN 6 5 | 6 | CRGB leds[NUM_LEDS]; 7 | 8 | void setup() { 9 | FastLED.addLeds(leds, NUM_LEDS); 10 | } 11 | 12 | void loop() { 13 | // Set your Valentine's Day color scheme 14 | CRGB red = CRGB(255, 0, 0); 15 | CRGB pink = CRGB(255, 105, 180); 16 | 17 | // Flashing effect 18 | for (int i = 0; i < 5; i++) { 19 | fill_solid(leds, NUM_LEDS, red); 20 | FastLED.show(); 21 | delay(500); 22 | fill_solid(leds, NUM_LEDS, CRGB::Black); 23 | FastLED.show(); 24 | delay(500); 25 | 26 | fill_solid(leds, NUM_LEDS, pink); 27 | FastLED.show(); 28 | delay(500); 29 | fill_solid(leds, NUM_LEDS, CRGB::Black); 30 | FastLED.show(); 31 | delay(500); 32 | } 33 | 34 | // Heartbeat effect 35 | for (int j = 0; j < 3; j++) { 36 | for (int brightness = 0; brightness < 255; brightness++) { 37 | fill_solid(leds, NUM_LEDS, pink); 38 | FastLED.show(); 39 | FastLED.setBrightness(brightness); 40 | delay(5); 41 | } 42 | for (int brightness = 255; brightness >= 0; brightness--) { 43 | fill_solid(leds, NUM_LEDS, pink); 44 | FastLED.show(); 45 | FastLED.setBrightness(brightness); 46 | delay(5); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Worm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #include 12 | 13 | Worm::Worm() : head_(0), tail_(0), speed_(0), head_dir_(0), tail_dir_(0), 14 | is_stretching_(true), color_(G35::max_color(rand())) { 15 | const float MIN = 0.1; 16 | const float MAX = 0.6; 17 | while (speed_ < MIN) { 18 | speed_ = MAX * ((float)rand() / (float)RAND_MAX); 19 | } 20 | head_dir_ = tail_dir_ = speed_; 21 | } 22 | 23 | void Worm::Do(G35& g35) { 24 | if (is_stretching_) { 25 | g35.set_color(head_, G35::MAX_INTENSITY, color_); 26 | head_ += head_dir_; 27 | } else { 28 | g35.set_color(tail_, G35::MAX_INTENSITY, COLOR_BLACK); 29 | tail_ += tail_dir_; 30 | } 31 | int8_t length = abs(head_ - tail_); 32 | if (length < UNIT) { 33 | is_stretching_ = true; 34 | } 35 | if (length >= UNIT * 4) { 36 | is_stretching_ = false; 37 | } 38 | if (head_ <= 0) { 39 | head_ = 0; 40 | head_dir_ = speed_; 41 | } 42 | uint8_t light_count = g35.get_light_count(); 43 | if (head_ >= light_count - 1) { 44 | head_ = light_count - 1; 45 | head_dir_ = -speed_; 46 | } 47 | if (tail_ <= 0) { 48 | tail_ = 0; 49 | tail_dir_ = speed_; 50 | } 51 | if (tail_ >= light_count - 1) { 52 | tail_ = light_count - 1; 53 | tail_dir_ = -speed_; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Worm.h: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | By Mike Tsao . 7 | 8 | See README for complete attributions. 9 | */ 10 | 11 | #ifndef INCLUDE_G35_PROGRAMS_WORM_H 12 | #define INCLUDE_G35_PROGRAMS_WORM_H 13 | 14 | #include 15 | 16 | class Worm { 17 | public: 18 | Worm(); 19 | void Do(G35& g35); 20 | 21 | void set_color(color_t color) { color_ = color; }; 22 | 23 | private: 24 | enum { UNIT = 2 }; 25 | 26 | float head_, tail_; 27 | float speed_, head_dir_, tail_dir_; 28 | bool is_stretching_; 29 | color_t color_; 30 | }; 31 | 32 | #endif // INCLUDE_G35_PROGRAMS_WORM_H 33 | -------------------------------------------------------------------------------- /examples/BasicExample/BasicExample.ino: -------------------------------------------------------------------------------- 1 | /* 2 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 3 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 4 | subject to the BSD license as described in the accompanying LICENSE file. 5 | 6 | See README for complete attributions. 7 | */ 8 | 9 | #include 10 | 11 | // Total # of lights on string (usually 50, 48, or 36). Maximum is 63, because 12 | // the protocol uses 6-bit addressing and bulb #63 is reserved for broadcast 13 | // messages. 14 | #define LIGHT_COUNT (50) 15 | 16 | // Arduino pin number. Pin 13 will blink the on-board LED. 17 | #define G35_PIN (13) 18 | 19 | G35String lights(G35_PIN, LIGHT_COUNT); 20 | 21 | void setup() { 22 | lights.enumerate(); 23 | lights.do_test_patterns(); 24 | } 25 | 26 | void loop() { 27 | lights.fill_color(0, LIGHT_COUNT, G35::MAX_INTENSITY, COLOR_RED); 28 | delay(1000); 29 | lights.fill_color(0, LIGHT_COUNT, G35::MAX_INTENSITY, COLOR_GREEN); 30 | delay(1000); 31 | 32 | static uint16_t c; 33 | lights.fill_color(0, LIGHT_COUNT, G35::MAX_INTENSITY, 34 | G35::rainbow_color(c++)); 35 | delay(1000); 36 | } 37 | -------------------------------------------------------------------------------- /examples/Go49ers2013/Go49ers2013.ino: -------------------------------------------------------------------------------- 1 | /* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- 2 | 3 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 4 | Copyright © 2013 The G35 Authors. Use, modification, and 5 | distribution are subject to the BSD license as described in the 6 | accompanying LICENSE file. 7 | 8 | This sample took the San Francisco 49ers all the way to the Super 9 | Bowl in the 2012-2013 season. Unfortunately its awesomeness was 10 | insufficient, and they failed to defeat the Baltimore Ravens in a 11 | heartbreaking 34-31 loss. 12 | 13 | By Mike Tsao . See README for complete 14 | attributions. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | // Arduino with Like A G35 shield (https://github.com/sowbug/like-a-g35). 24 | // First string on pin 8. Second on 9. My roofline isn't quite long enough 25 | // for 100 lights, so I have the final 10 hidden. 26 | G35String lights_1(8, 50, 50, 0, false); 27 | G35String lights_2(9, 40); 28 | 29 | class RedYellowChase : public LightProgram { 30 | public: 31 | RedYellowChase(G35& g35); 32 | uint32_t Do(); 33 | static color_t color_sequence(uint16_t sequence); 34 | 35 | private: 36 | uint8_t count_; 37 | uint16_t sequence_; 38 | }; 39 | 40 | RedYellowChase::RedYellowChase(G35& g35) 41 | : LightProgram(g35), 42 | count_(1), 43 | sequence_(0) {} 44 | 45 | uint32_t RedYellowChase::Do() { 46 | g35_.fill_sequence(0, count_, sequence_, 5, 255, color_sequence); 47 | if (count_ < light_count_) { 48 | ++count_; 49 | } else { 50 | ++sequence_; 51 | } 52 | return bulb_frame_; 53 | } 54 | 55 | // static 56 | color_t RedYellowChase::color_sequence(uint16_t sequence) { 57 | return sequence % 2 ? COLOR_RED : COLOR_YELLOW; 58 | } 59 | 60 | const int PROGRAM_COUNT = 1; 61 | 62 | G35StringGroup string_group; 63 | 64 | LightProgram* CreateProgram(uint8_t program_index) { 65 | return new RedYellowChase(string_group); 66 | } 67 | 68 | // How long each program should run. 69 | #define PROGRAM_DURATION_SECONDS (60) 70 | 71 | ProgramRunner runner(CreateProgram, PROGRAM_COUNT, PROGRAM_DURATION_SECONDS); 72 | 73 | // http://www.utopiamechanicus.com/77/better-arduino-random-numbers/ 74 | // We assume A0 and A1 are disconnected. 75 | uint32_t seedOut(unsigned int noOfBits) { 76 | uint32_t seed = 0, limit = 99; 77 | int bit0 = 0, bit1 = 0; 78 | while (noOfBits--) { 79 | for (int i = 0; i < limit; ++i) { 80 | bit0 = analogRead(0) & 1; 81 | bit1 = analogRead(1) & 1; 82 | if (bit1 != bit0) 83 | break; 84 | } 85 | seed = (seed << 1) | bit1; 86 | } 87 | return seed; 88 | } 89 | 90 | void setup() { 91 | uint32_t seed = seedOut(32); 92 | randomSeed(seed); 93 | seed &= 0xff; 94 | // random() isn't very random. But this seed generator works quite well. 95 | while (seed--) { 96 | random(); 97 | } 98 | 99 | delay(50); 100 | lights_1.enumerate(); 101 | lights_2.enumerate(); 102 | 103 | lights_1.do_test_patterns(); 104 | lights_2.do_test_patterns(); 105 | 106 | string_group.AddString(&lights_1); 107 | string_group.AddString(&lights_2); 108 | } 109 | 110 | void loop() { 111 | runner.loop(); 112 | } 113 | -------------------------------------------------------------------------------- /examples/MultipleIndependentStrings/MultipleIndependentStrings.ino: -------------------------------------------------------------------------------- 1 | // A demonstration of multiple independent strings on a single controller. 2 | // 3 | // By Mike Tsao 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | // How long each program should run. 11 | #define PROGRAM_DURATION_SECONDS (30) 12 | 13 | #define LIGHT_COUNT (50) 14 | 15 | #define USING_TEENSY_AS_LEONARDO (0) 16 | 17 | #if USING_TEENSY_AS_LEONARDO 18 | // A Teensy 2.0 that's been flashed with the Arduino Leonardo bootloader (thus 19 | // permanently destroying the HalfKay bootloader that ships with the Teensy). 20 | // The first string is connected to D6, and the second to B4. 21 | G35String lights_1(12, LIGHT_COUNT); 22 | G35String lights_2(8, LIGHT_COUNT); 23 | #else 24 | // Standard Arduino, string 1 on Pin 13, string 2 on Pin 12. 25 | G35String lights_1(13, LIGHT_COUNT); 26 | G35String lights_2(12, LIGHT_COUNT); 27 | #endif 28 | 29 | const int PROGRAM_COUNT = StockProgramGroup::ProgramCount + 30 | PlusProgramGroup::ProgramCount; 31 | 32 | StockProgramGroup stock_programs; 33 | PlusProgramGroup plus_programs; 34 | 35 | LightProgram* CreateProgram(G35& lights, uint8_t program_index) { 36 | randomSeed(rand() + analogRead(0)); 37 | 38 | if (program_index < StockProgramGroup::ProgramCount) { 39 | return stock_programs.CreateProgram(lights, program_index); 40 | } 41 | program_index -= StockProgramGroup::ProgramCount; 42 | 43 | if (program_index < PlusProgramGroup::ProgramCount) { 44 | return plus_programs.CreateProgram(lights, program_index); 45 | } 46 | program_index -= PlusProgramGroup::ProgramCount; 47 | 48 | return NULL; 49 | } 50 | 51 | LightProgram* CreateProgram_1(uint8_t program_index) { 52 | return CreateProgram(lights_1, program_index); 53 | } 54 | 55 | LightProgram* CreateProgram_2(uint8_t program_index) { 56 | // If you'd prefer both strings to simultaneously run individual instances of 57 | // the same program, remove the + 1 offset. 58 | return CreateProgram(lights_2, program_index + 1); 59 | } 60 | 61 | ProgramRunner runner_1(CreateProgram_1, PROGRAM_COUNT, 62 | PROGRAM_DURATION_SECONDS); 63 | ProgramRunner runner_2(CreateProgram_2, PROGRAM_COUNT, 64 | PROGRAM_DURATION_SECONDS); 65 | 66 | void setup() { 67 | randomSeed(analogRead(0)); 68 | 69 | delay(50); 70 | lights_1.enumerate(); 71 | lights_2.enumerate(); 72 | delay(50); 73 | 74 | lights_1.do_test_patterns(); 75 | lights_2.do_test_patterns(); 76 | } 77 | 78 | void loop() { 79 | runner_1.loop(); 80 | runner_2.loop(); 81 | } 82 | -------------------------------------------------------------------------------- /examples/MultipleStringsAsOne/MultipleStringsAsOne.ino: -------------------------------------------------------------------------------- 1 | // A demonstration of multiple strings acting as a single large one. 2 | // 3 | // By Mike Tsao 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // How long each program should run. 12 | #define PROGRAM_DURATION_SECONDS (30) 13 | 14 | // Standard Arduino, string 1 on Pin 13, string 2 on Pin 12. 15 | G35String lights_1(13, 50); 16 | G35String lights_2(12, 50); 17 | G35StringGroup string_group; 18 | 19 | const int PROGRAM_COUNT = StockProgramGroup::ProgramCount + 20 | PlusProgramGroup::ProgramCount; 21 | 22 | StockProgramGroup stock_programs; 23 | PlusProgramGroup plus_programs; 24 | 25 | LightProgram* CreateProgram(uint8_t program_index) { 26 | randomSeed(rand() + analogRead(0)); 27 | 28 | if (program_index < StockProgramGroup::ProgramCount) { 29 | return stock_programs.CreateProgram(string_group, program_index); 30 | } 31 | program_index -= StockProgramGroup::ProgramCount; 32 | 33 | if (program_index < PlusProgramGroup::ProgramCount) { 34 | return plus_programs.CreateProgram(string_group, program_index); 35 | } 36 | program_index -= PlusProgramGroup::ProgramCount; 37 | 38 | return NULL; 39 | } 40 | 41 | ProgramRunner runner(CreateProgram, PROGRAM_COUNT, PROGRAM_DURATION_SECONDS); 42 | 43 | void setup() { 44 | randomSeed(analogRead(0)); 45 | 46 | delay(50); 47 | lights_1.enumerate(); 48 | lights_2.enumerate(); 49 | delay(50); 50 | 51 | lights_1.do_test_patterns(); 52 | lights_2.do_test_patterns(); 53 | 54 | string_group.AddString(&lights_1); 55 | string_group.AddString(&lights_2); 56 | } 57 | 58 | void loop() { 59 | runner.loop(); 60 | } 61 | -------------------------------------------------------------------------------- /examples/StockPlus/StockPlus.ino: -------------------------------------------------------------------------------- 1 | // StockPlus: A Sunday afternoon's worth of work duplicating the stock G-35 2 | // controller programs, plus a few extra thrown in for fun. Some are 3 | // intentionally done a little differently from the originals because I thought 4 | // they looked better. 5 | // 6 | // By Mike Tsao 7 | // 8 | // See http://www.youtube.com/watch?v=7al1vIinhuo for original patterns. 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | // How long each program should run. 16 | #define PROGRAM_DURATION_SECONDS (30) 17 | 18 | #define LIGHT_COUNT (50) 19 | 20 | // Arduino pin number. Pin 13 will blink the on-board LED. 21 | #define G35_PIN (13) 22 | 23 | G35String lights(G35_PIN, LIGHT_COUNT); 24 | 25 | const int PROGRAM_COUNT = StockProgramGroup::ProgramCount + 26 | PlusProgramGroup::ProgramCount; 27 | 28 | StockProgramGroup stock_programs; 29 | PlusProgramGroup plus_programs; 30 | 31 | LightProgram* CreateProgram(uint8_t program_index) { 32 | randomSeed(rand() + analogRead(0)); 33 | 34 | if (program_index < StockProgramGroup::ProgramCount) { 35 | return stock_programs.CreateProgram(lights, program_index); 36 | } 37 | program_index -= StockProgramGroup::ProgramCount; 38 | 39 | if (program_index < PlusProgramGroup::ProgramCount) { 40 | return plus_programs.CreateProgram(lights, program_index); 41 | } 42 | program_index -= PlusProgramGroup::ProgramCount; 43 | 44 | return NULL; 45 | } 46 | 47 | ProgramRunner runner(CreateProgram, PROGRAM_COUNT, PROGRAM_DURATION_SECONDS); 48 | 49 | void setup() { 50 | randomSeed(analogRead(0)); 51 | 52 | delay(50); 53 | lights.enumerate(); 54 | delay(50); 55 | 56 | lights.do_test_patterns(); 57 | } 58 | 59 | void loop() { 60 | runner.loop(); 61 | } 62 | -------------------------------------------------------------------------------- /examples/Ticon2011/Ticon2011.ino: -------------------------------------------------------------------------------- 1 | /* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- 2 | 3 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 4 | Copyright © 2011 The G35 Authors. Use, modification, and distribution are 5 | subject to the BSD license as described in the accompanying LICENSE file. 6 | 7 | Ticon2011.ino is the code that I used for Christmas 2011 at my home. It's yet 8 | another demonstration of working code. 9 | 10 | By Mike Tsao . See README for complete attributions. 11 | */ 12 | 13 | // If defined, then a 38KHz IR receiver is supplying data on pin 11. I didn't 14 | // really use this much; if it detects any recognized remote code, it skips to 15 | // the next program. So in theory people driving by my house who happen to have 16 | // a TV remote in their car could stop and change the program. 17 | // 18 | // Pretty much any of these IR receivers will work. I used a Vishay Semi 19 | // TSOP58038 (http://octopart.com/partsearch#search/requestData&q=TSOP58038). 20 | #define USE_REMOTE 1 21 | 22 | // If defined, then the hardware is an Arduino. If not, then it's a Teensy. 23 | // More described below. I used this switch because I had an Arduino in the 24 | // house when I was writing new programs, then ran outside in the cold with my 25 | // laptop to reprogram the Teensy that was running the real lights. 26 | #define ARDUINO_HW 1 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #ifdef USE_REMOTE 34 | // Get at https://github.com/shirriff/Arduino-IRremote 35 | #include 36 | #endif 37 | 38 | #ifdef ARDUINO_HW 39 | // A regular Arduino. First string on pin 13, second on 12. 40 | G35String lights_1(13, 50, 50, 0, false); 41 | G35String lights_2(12, 41); 42 | 43 | #ifdef USE_REMOTE 44 | IRrecv ir(11); // IR receiver on pin 11. 45 | decode_results ir_results; 46 | #endif 47 | 48 | #else 49 | // A Teensy 2.0 that's been flashed with the Arduino Leonardo bootloader (thus 50 | // permanently destroying the HalfKay bootloader that ships with the Teensy). 51 | // The first string is connected to D6, and the second to B4. 52 | G35String lights_1(12, 50, 50, 0, false); 53 | G35String lights_2(8, 41); 54 | #endif 55 | 56 | const int PROGRAM_COUNT = StockProgramGroup::ProgramCount + 57 | PlusProgramGroup::ProgramCount; 58 | 59 | StockProgramGroup stock_programs; 60 | PlusProgramGroup plus_programs; 61 | G35StringGroup string_group; 62 | 63 | LightProgram* CreateProgram(uint8_t program_index) { 64 | program_index = random() % PROGRAM_COUNT; 65 | 66 | if (program_index < StockProgramGroup::ProgramCount) { 67 | return stock_programs.CreateProgram(string_group, program_index); 68 | } 69 | program_index -= StockProgramGroup::ProgramCount; 70 | 71 | if (program_index < PlusProgramGroup::ProgramCount) { 72 | return plus_programs.CreateProgram(string_group, program_index); 73 | } 74 | program_index -= PlusProgramGroup::ProgramCount; 75 | 76 | return NULL; 77 | } 78 | 79 | // How long each program should run. 80 | #define PROGRAM_DURATION_SECONDS (60) 81 | 82 | ProgramRunner runner(CreateProgram, PROGRAM_COUNT, PROGRAM_DURATION_SECONDS); 83 | 84 | // http://www.utopiamechanicus.com/77/better-arduino-random-numbers/ 85 | // We assume A0 and A1 are disconnected. 86 | uint32_t seedOut(unsigned int noOfBits) { 87 | uint32_t seed = 0, limit = 99; 88 | int bit0 = 0, bit1 = 0; 89 | while (noOfBits--) { 90 | for (int i = 0; i < limit; ++i) { 91 | bit0 = analogRead(0) & 1; 92 | bit1 = analogRead(1) & 1; 93 | if (bit1 != bit0) 94 | break; 95 | } 96 | seed = (seed << 1) | bit1; 97 | } 98 | return seed; 99 | } 100 | 101 | void setup() { 102 | uint32_t seed = seedOut(32); 103 | randomSeed(seed); 104 | seed &= 0xff; 105 | // random() isn't very random. But this seed generator works quite well. 106 | while (seed--) { 107 | random(); 108 | } 109 | 110 | #ifdef USE_REMOTE 111 | ir.enableIRIn(); 112 | #endif 113 | 114 | delay(50); 115 | lights_1.enumerate(); 116 | lights_2.enumerate(); 117 | 118 | lights_1.do_test_patterns(); 119 | lights_2.do_test_patterns(); 120 | 121 | string_group.AddString(&lights_1); 122 | string_group.AddString(&lights_2); 123 | } 124 | 125 | void loop() { 126 | runner.loop(); 127 | 128 | #ifdef USE_REMOTE 129 | if (ir.decode(&ir_results)) { 130 | runner.switch_program(); 131 | ir.resume(); 132 | } 133 | #endif 134 | } 135 | -------------------------------------------------------------------------------- /examples/TiconHalloween2012/TiconHalloween2012.ino: -------------------------------------------------------------------------------- 1 | /* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- 2 | 3 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 4 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 5 | subject to the BSD license as described in the accompanying LICENSE file. 6 | 7 | This file is the code that I used for Halloween 2012 at my home. 8 | 9 | By Mike Tsao . See README for complete attributions. 10 | */ 11 | 12 | // If defined, then the hardware is an Arduino. If not, then it's a Teensy. 13 | // More described below. I used this switch because I had an Arduino in the 14 | // house when I was writing new programs, then ran outside in the cold with my 15 | // laptop to reprogram the Teensy that was running the real lights. 16 | #define ARDUINO_HW 1 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #ifdef ARDUINO_HW 24 | // A regular Arduino with Like A G35 shield. 25 | // First string on pin 8. Second on 9. 26 | G35String lights_1(8, 50, 50, 0, false); 27 | G35String lights_2(9, 41); 28 | 29 | #else 30 | // A Teensy 2.0 that's been flashed with the Arduino Leonardo bootloader (thus 31 | // permanently destroying the HalfKay bootloader that ships with the Teensy). 32 | // The first string is connected to D6, and the second to B4. 33 | G35String lights_1(12, 50, 50, 0, false); 34 | G35String lights_2(8, 41); 35 | #endif 36 | 37 | const int PROGRAM_COUNT = HalloweenProgramGroup::ProgramCount; 38 | 39 | HalloweenProgramGroup programs; 40 | G35StringGroup string_group; 41 | 42 | LightProgram* CreateProgram(uint8_t program_index) { 43 | return programs.CreateProgram(string_group, program_index); 44 | } 45 | 46 | // How long each program should run. 47 | #define PROGRAM_DURATION_SECONDS (60) 48 | 49 | ProgramRunner runner(CreateProgram, PROGRAM_COUNT, PROGRAM_DURATION_SECONDS); 50 | 51 | // http://www.utopiamechanicus.com/77/better-arduino-random-numbers/ 52 | // We assume A0 and A1 are disconnected. 53 | uint32_t seedOut(unsigned int noOfBits) { 54 | uint32_t seed = 0, limit = 99; 55 | int bit0 = 0, bit1 = 0; 56 | while (noOfBits--) { 57 | for (int i = 0; i < limit; ++i) { 58 | bit0 = analogRead(0) & 1; 59 | bit1 = analogRead(1) & 1; 60 | if (bit1 != bit0) 61 | break; 62 | } 63 | seed = (seed << 1) | bit1; 64 | } 65 | return seed; 66 | } 67 | 68 | void setup() { 69 | uint32_t seed = seedOut(32); 70 | randomSeed(seed); 71 | seed &= 0xff; 72 | // random() isn't very random. But this seed generator works quite well. 73 | while (seed--) { 74 | random(); 75 | } 76 | 77 | delay(50); 78 | lights_1.enumerate(); 79 | lights_2.enumerate(); 80 | 81 | lights_1.do_test_patterns(); 82 | lights_2.do_test_patterns(); 83 | 84 | string_group.AddString(&lights_1); 85 | string_group.AddString(&lights_2); 86 | } 87 | 88 | void loop() { 89 | runner.loop(); 90 | } 91 | -------------------------------------------------------------------------------- /examples/TiconXmas2012/TiconXmas2012.ino: -------------------------------------------------------------------------------- 1 | /* -*- mode: c; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- 2 | 3 | G35: An Arduino library for GE Color Effects G-35 holiday lights. 4 | Copyright © 2012 The G35 Authors. Use, modification, and distribution are 5 | subject to the BSD license as described in the accompanying LICENSE file. 6 | 7 | TiconXmas2012.ino is the code that I used for Christmas 2012 at my home. 8 | It's yet another demonstration of working code. 9 | 10 | By Mike Tsao . See README for complete attributions. 11 | */ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | // Arduino with Like A G35 shield (https://github.com/sowbug/like-a-g35). 20 | // First string on pin 8. Second on 9. My roofline isn't quite long enough 21 | // for 100 lights, so I have the final 10 hidden. 22 | G35String lights_1(8, 50, 50, 0, false); 23 | G35String lights_2(9, 40); 24 | 25 | const int PROGRAM_COUNT = StockProgramGroup::ProgramCount + 26 | PlusProgramGroup::ProgramCount; 27 | 28 | StockProgramGroup stock_programs; 29 | PlusProgramGroup plus_programs; 30 | G35StringGroup string_group; 31 | 32 | LightProgram* CreateProgram(uint8_t program_index) { 33 | program_index = random() % PROGRAM_COUNT; 34 | 35 | if (program_index < StockProgramGroup::ProgramCount) { 36 | return stock_programs.CreateProgram(string_group, program_index); 37 | } 38 | program_index -= StockProgramGroup::ProgramCount; 39 | 40 | if (program_index < PlusProgramGroup::ProgramCount) { 41 | return plus_programs.CreateProgram(string_group, program_index); 42 | } 43 | program_index -= PlusProgramGroup::ProgramCount; 44 | 45 | return NULL; 46 | } 47 | 48 | // How long each program should run. 49 | #define PROGRAM_DURATION_SECONDS (90) 50 | 51 | ProgramRunner runner(CreateProgram, PROGRAM_COUNT, PROGRAM_DURATION_SECONDS); 52 | 53 | // http://www.utopiamechanicus.com/77/better-arduino-random-numbers/ 54 | // We assume A0 and A1 are disconnected. 55 | uint32_t seedOut(unsigned int noOfBits) { 56 | uint32_t seed = 0, limit = 99; 57 | int bit0 = 0, bit1 = 0; 58 | while (noOfBits--) { 59 | for (int i = 0; i < limit; ++i) { 60 | bit0 = analogRead(0) & 1; 61 | bit1 = analogRead(1) & 1; 62 | if (bit1 != bit0) 63 | break; 64 | } 65 | seed = (seed << 1) | bit1; 66 | } 67 | return seed; 68 | } 69 | 70 | void setup() { 71 | uint32_t seed = seedOut(32); 72 | randomSeed(seed); 73 | seed &= 0xff; 74 | // random() isn't very random. But this seed generator works quite well. 75 | while (seed--) { 76 | random(); 77 | } 78 | 79 | delay(50); 80 | lights_1.enumerate(); 81 | lights_2.enumerate(); 82 | 83 | lights_1.do_test_patterns(); 84 | lights_2.do_test_patterns(); 85 | 86 | string_group.AddString(&lights_1); 87 | string_group.AddString(&lights_2); 88 | } 89 | 90 | void loop() { 91 | runner.loop(); 92 | } 93 | -------------------------------------------------------------------------------- /images/green_lights.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sowbug/G35Arduino/0d7ad1f5c560ed4155c89cfd20884d6be27f2cf0/images/green_lights.jpg -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | GEColorEffects KEYWORD1 2 | set_color KEYWORD2 3 | color KEYWORD2 4 | color_hue KEYWORD2 5 | fill_color KEYWORD2 6 | fill_color_same KEYWORD2 7 | enumerate KEYWORD2 --------------------------------------------------------------------------------