129 lines
3.1 KiB
Arduino
129 lines
3.1 KiB
Arduino
// 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);
|
|
}
|