// Mr. Christmas powerline RGB protocol // 7-bit command: PPP M BGR (MSB first) // // Idle HIGH = string powered; brief LOW pulses encode bits. // Short pause ~= 0, long pause ~= 1. #if defined(ESP8266) || defined(ESP32) const int command_pin = D1; // MOSFET gate #else const int command_pin = 8; #endif const int PULSE_DURATION = 100; // microseconds const int SHORT_PAUSE = 4964; // bit 0 const int LONG_PAUSE = 16992; // bit 1 // 3bits: PPP enum Pattern { STEADY = 0, // 000 FADE = 1, // 001 SPARKLE = 2, // 010 FIREFLY = 3, // 011 TWINKLE = 4, // 100 - dark + colored flashes FAST_SPARKLE = 5, // 101 ANTI_SPARKLE = 6, // 110 - black sparkles FAST_TWINKLE = 7, // 111 }; // 4bits: MBGR // M=0: BGR (solid colors) // M=1: palette enum Color { COLOR_OFF = 0, // 0000 RED = 1, // 0001 GREEN = 2, // 0010 YELLOW = 3, // 0011 BLUE = 4, // 0100 MAGENTA = 5, // 0101 CYAN = 6, // 0110 WHITE = 7, // 0111 MULTI = 8, // 1000 - multi-color CHRISTMAS = 9, // 1001 - red/white/green JULY4 = 10, // 1010 - red/white/blue }; Pattern patterns[] = { STEADY, FADE, SPARKLE, FIREFLY, TWINKLE, FAST_SPARKLE, ANTI_SPARKLE, FAST_TWINKLE, }; const char *pattern_names[] = { "Steady", "Fade", "Sparkle", "Firefly", "Twinkle", "FastSparkle", "AntiSparkle", "FastTwinkle", }; Color colors[] = { COLOR_OFF, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE, MULTI, CHRISTMAS, JULY4, }; const char *color_names[] = { "Off", "Red", "Green", "Yellow", "Blue", "Magenta", "Cyan", "White", "Multi", "Christmas", "July4", }; /** * Send a single short pulse of "off". */ void send_pulse() { noInterrupts(); digitalWrite(command_pin, LOW); delayMicroseconds(PULSE_DURATION); digitalWrite(command_pin, HIGH); interrupts(); } /** * Send a single bit. */ void send_bit(bool b) { send_pulse(); delayMicroseconds(b ? LONG_PAUSE : SHORT_PAUSE); } /** * Send a whole 7-bit command (PPP M BGR), then an end pulse. */ void send_command(int cmd) { for (int mask = 0x40; mask > 0; mask >>= 1) { send_bit(cmd & mask); } send_pulse(); delayMicroseconds(LONG_PAUSE); } /** * Send a whole command based on a pattern and color/palette. */ void send_command(Pattern pattern, Color color) { send_command((pattern << 4) | color); } void setup() { pinMode(command_pin, OUTPUT); digitalWrite(command_pin, HIGH); Serial.begin(9600); delay(500); Serial.println(); Serial.println("Full demo"); delay(1000); } void loop() { // Demo: each pattern x colors/palettes. for (unsigned p = 0; p < sizeof(patterns) / sizeof(patterns[0]); p++) { for (unsigned c = 0; c < sizeof(colors) / sizeof(colors[0]); c++) { if (colors[c] == COLOR_OFF && patterns[p] != FAST_SPARKLE) { // Off is only meaningful with FastSparkle (dark + fast white sparkles). continue; } send_command(patterns[p], colors[c]); Serial.print(pattern_names[p]); Serial.print(" + "); Serial.println(color_names[c]); delay(10000); } } send_command(STEADY, COLOR_OFF); Serial.println("Off"); delay(5000); }