|
| 1 | +#include <NeoPixelBus.h> |
| 2 | +//////////////////////////////////////////////////////////////////////////////////////////////////// |
| 3 | +///////////////////////// CONFIG SECTION STARTS ///////////////////////////// |
| 4 | +//////////////////////////////////////////////////////////////////////////////////////////////////// |
| 5 | + |
| 6 | +#define THIS_IS_RGBW // RGBW SK6812, otherwise comment it |
| 7 | +bool skipFirstLed = true; // if set the first led in the strip will be set to black (for level shifters) |
| 8 | +int serialSpeed = 2000000; // serial port speed |
| 9 | + |
| 10 | +//////////////////////////////////////////////////////////////////////////////////////////////////// |
| 11 | +///////////////////////// CONFIG SECTION ENDS ///////////////////////////// |
| 12 | +//////////////////////////////////////////////////////////////////////////////////////////////////// |
| 13 | + |
| 14 | +int pixelCount = 16; // This is dynamic, don't change it |
| 15 | + |
| 16 | +#ifdef THIS_IS_RGBW |
| 17 | + #define LED_TYPE NeoGrbwFeature |
| 18 | +#else |
| 19 | + #define LED_TYPE NeoGrbFeature |
| 20 | +#endif |
| 21 | + |
| 22 | + |
| 23 | +NeoPixelBus<LED_TYPE, NeoEsp8266Uart1800KbpsMethod>* strip = NULL; |
| 24 | + |
| 25 | +void Init(int count) |
| 26 | +{ |
| 27 | + if (strip != NULL) |
| 28 | + delete strip; |
| 29 | + |
| 30 | + pixelCount = count; |
| 31 | + strip = new NeoPixelBus<LED_TYPE, NeoEsp8266Uart1800KbpsMethod>(pixelCount); |
| 32 | +} |
| 33 | + |
| 34 | +enum class AwaProtocol { |
| 35 | + HEADER_A, |
| 36 | + HEADER_w, |
| 37 | + HEADER_a, |
| 38 | + HEADER_HI, |
| 39 | + HEADER_LO, |
| 40 | + HEADER_CRC, |
| 41 | + RED, |
| 42 | + GREEN, |
| 43 | + BLUE, |
| 44 | + FLETCHER1, |
| 45 | + FLETCHER2 |
| 46 | +}; |
| 47 | + |
| 48 | +// static data buffer for the loop |
| 49 | +uint8_t buffer[4096]; |
| 50 | +AwaProtocol state = AwaProtocol::HEADER_A; |
| 51 | +uint8_t CRC = 0; |
| 52 | +uint16_t count = 0; |
| 53 | +uint16_t currentPixel = 0; |
| 54 | +uint16_t fletcher1 = 0; |
| 55 | +uint16_t fletcher2 = 0; |
| 56 | + |
| 57 | +#ifdef THIS_IS_RGBW |
| 58 | +RgbwColor inputColor; |
| 59 | +uint8_t rChannel[256]; |
| 60 | +uint8_t gChannel[256]; |
| 61 | +uint8_t bChannel[256]; |
| 62 | + |
| 63 | +#else |
| 64 | +RgbColor inputColor; |
| 65 | +#endif |
| 66 | + |
| 67 | +void readSerialData() |
| 68 | +{ |
| 69 | + uint16_t bufferPointer = 0; |
| 70 | + uint16_t internalIndex = min(Serial.available(), 4096); |
| 71 | + |
| 72 | + if (internalIndex > 0) |
| 73 | + internalIndex = Serial.readBytes(buffer, internalIndex); |
| 74 | + |
| 75 | + while (bufferPointer < internalIndex) |
| 76 | + { |
| 77 | + byte input = buffer[bufferPointer++]; |
| 78 | + switch (state) |
| 79 | + { |
| 80 | + case AwaProtocol::HEADER_A: |
| 81 | + if (input == 'A') state = AwaProtocol::HEADER_w; |
| 82 | + break; |
| 83 | + |
| 84 | + case AwaProtocol::HEADER_w: |
| 85 | + if (input == 'w') state = AwaProtocol::HEADER_a; |
| 86 | + else state = AwaProtocol::HEADER_A; |
| 87 | + break; |
| 88 | + |
| 89 | + case AwaProtocol::HEADER_a: |
| 90 | + if (input == 'a') state = AwaProtocol::HEADER_HI; |
| 91 | + else state = AwaProtocol::HEADER_A; |
| 92 | + break; |
| 93 | + |
| 94 | + case AwaProtocol::HEADER_HI: |
| 95 | + currentPixel = 0; |
| 96 | + count = input * 0x100; |
| 97 | + CRC = input; |
| 98 | + fletcher1 = 0; |
| 99 | + fletcher2 = 0; |
| 100 | + state = AwaProtocol::HEADER_LO; |
| 101 | + break; |
| 102 | + |
| 103 | + case AwaProtocol::HEADER_LO: |
| 104 | + count += input; |
| 105 | + CRC = CRC ^ input ^ 0x55; |
| 106 | + state = AwaProtocol::HEADER_CRC; |
| 107 | + break; |
| 108 | + |
| 109 | + case AwaProtocol::HEADER_CRC: |
| 110 | + if (CRC == input) |
| 111 | + { |
| 112 | + if (count+1 != pixelCount) Init(count+1); |
| 113 | + state = AwaProtocol::RED; |
| 114 | + } |
| 115 | + else |
| 116 | + state = AwaProtocol::HEADER_A; |
| 117 | + break; |
| 118 | + |
| 119 | + case AwaProtocol::RED: |
| 120 | + inputColor.R = input; |
| 121 | + fletcher1 = (fletcher1 + (uint16_t)input) % 255; |
| 122 | + fletcher2 = (fletcher2 + fletcher1) % 255; |
| 123 | + |
| 124 | + state = AwaProtocol::GREEN; |
| 125 | + break; |
| 126 | + |
| 127 | + case AwaProtocol::GREEN: |
| 128 | + inputColor.G = input; |
| 129 | + fletcher1 = (fletcher1 + (uint16_t)input) % 255; |
| 130 | + fletcher2 = (fletcher2 + fletcher1) % 255; |
| 131 | + |
| 132 | + state = AwaProtocol::BLUE; |
| 133 | + break; |
| 134 | + |
| 135 | + case AwaProtocol::BLUE: |
| 136 | + inputColor.B = input; |
| 137 | + |
| 138 | + #ifdef THIS_IS_RGBW |
| 139 | + inputColor.W = min(rChannel[inputColor.R], |
| 140 | + min(gChannel[inputColor.G], |
| 141 | + bChannel[inputColor.B])); |
| 142 | + inputColor.R -= rChannel[inputColor.W]; |
| 143 | + inputColor.G -= gChannel[inputColor.W]; |
| 144 | + inputColor.B -= bChannel[inputColor.W]; |
| 145 | + #endif |
| 146 | + |
| 147 | + fletcher1 = (fletcher1 + (uint16_t)input) % 255; |
| 148 | + fletcher2 = (fletcher2 + fletcher1) % 255; |
| 149 | + |
| 150 | + if (currentPixel == 0 && skipFirstLed) |
| 151 | + { |
| 152 | + #ifdef THIS_IS_RGBW |
| 153 | + strip->SetPixelColor(currentPixel++, RgbwColor(0, 0, 0, 0)); |
| 154 | + #else |
| 155 | + strip->SetPixelColor(currentPixel++, RgbColor(0, 0, 0)); |
| 156 | + #endif |
| 157 | + } |
| 158 | + else |
| 159 | + setStripPixel(currentPixel++, inputColor); |
| 160 | + |
| 161 | + if (count-- > 0) state = AwaProtocol::RED; |
| 162 | + else state = AwaProtocol::FLETCHER1; |
| 163 | + break; |
| 164 | + |
| 165 | + case AwaProtocol::FLETCHER1: |
| 166 | + if (input != fletcher1) state = AwaProtocol::HEADER_A; |
| 167 | + else state = AwaProtocol::FLETCHER2; |
| 168 | + break; |
| 169 | + |
| 170 | + case AwaProtocol::FLETCHER2: |
| 171 | + if (input == fletcher2) strip->Show(); |
| 172 | + state = AwaProtocol::HEADER_A; |
| 173 | + break; |
| 174 | + } |
| 175 | + } |
| 176 | +} |
| 177 | + |
| 178 | +#ifdef THIS_IS_RGBW |
| 179 | +void setStripPixel(uint16_t pix, RgbwColor& inputColor) |
| 180 | +{ |
| 181 | + if (pix < pixelCount) |
| 182 | + { |
| 183 | + strip->SetPixelColor(pix, inputColor); |
| 184 | + } |
| 185 | +} |
| 186 | +#else |
| 187 | +void setStripPixel(uint16_t pix, RgbColor& inputColor) |
| 188 | +{ |
| 189 | + if (pix < pixelCount) |
| 190 | + { |
| 191 | + strip->SetPixelColor(pix, inputColor); |
| 192 | + } |
| 193 | +} |
| 194 | +#endif |
| 195 | + |
| 196 | +void setup() |
| 197 | +{ |
| 198 | + // Init serial port |
| 199 | + Serial.begin(serialSpeed); |
| 200 | + |
| 201 | + // Init NeoPixelBus |
| 202 | + Init(pixelCount); |
| 203 | + strip->Begin(); |
| 204 | + |
| 205 | + #ifdef THIS_IS_RGBW |
| 206 | + // prepare |
| 207 | + for (int i = 0; i < 256; i++) |
| 208 | + { |
| 209 | + uint32_t rCorrection = 0xB0 * (uint32_t)i; // adjust red -> white in 0-0xFF range |
| 210 | + uint32_t gCorrection = 0xB0 * (uint32_t)i; // adjust green -> white in 0-0xFF range |
| 211 | + uint32_t bCorrection = 0x80 * (uint32_t)i; // adjust blue -> white in 0-0xFF range |
| 212 | + |
| 213 | + rCorrection /= 0xFF; |
| 214 | + gCorrection /= 0xFF; |
| 215 | + bCorrection /= 0xFF; |
| 216 | + |
| 217 | + rChannel[i] = (uint8_t)rCorrection; |
| 218 | + gChannel[i] = (uint8_t)gCorrection; |
| 219 | + bChannel[i] = (uint8_t)bCorrection; |
| 220 | + } |
| 221 | + #endif |
| 222 | + |
| 223 | + // Say ambilight like "Hello" to the world |
| 224 | + for (int i = 0; i < 9; i++) |
| 225 | + { |
| 226 | + if (i < 3) |
| 227 | + strip->SetPixelColor(0, RgbColor(((i + 1) * 80) % 255, 0, 0)); |
| 228 | + else if (i < 6) |
| 229 | + strip->SetPixelColor(0, RgbColor(0, ((6 - i) * 80) % 255, 0)); |
| 230 | + else |
| 231 | + strip->SetPixelColor(0, RgbColor(0, 0, ((i - 5) * 80) % 255)); |
| 232 | + |
| 233 | + strip->Show(); |
| 234 | + delay(200); |
| 235 | + } |
| 236 | + |
| 237 | + // Clear it |
| 238 | + strip->SetPixelColor(0, RgbColor(0, 0, 0)); |
| 239 | + strip->Show(); |
| 240 | +} |
| 241 | + |
| 242 | +void loop() |
| 243 | +{ |
| 244 | + readSerialData(); |
| 245 | +} |
0 commit comments