13 #ifndef FRONT_LOGIC_PIN
14 #if defined(REELTWO_TEENSY)
15 #define FRONT_LOGIC_PIN 21
16 #elif defined(REELTWO_ZERO)
17 #define FRONT_LOGIC_PIN 5
18 #elif defined(REELTWO_AVR_MEGA)
19 #define FRONT_LOGIC_PIN 5
20 #elif defined(REELTWO_AVR)
22 #define FRONT_LOGIC_PIN 6
23 #elif defined(REELTWO_RP2040)
24 #define FRONT_LOGIC_PIN 15
25 #define FRONT_LOGIC_CLOCK_PIN 2
27 #define FRONT_LOGIC_PIN 15
28 #define FRONT_LOGIC_CLOCK_PIN 2
30 #error Unsupported platform
34 #ifndef REAR_LOGIC_PIN
35 #if defined(REELTWO_TEENSY)
36 #define REAR_LOGIC_PIN 22
37 #elif defined(REELTWO_ZERO)
38 #define REAR_LOGIC_PIN 3
39 #elif defined(REELTWO_AVR_MEGA)
40 #define REAR_LOGIC_PIN 6
41 #define REAR_LOGIC_CLOCK_PIN 7
42 #elif defined(REELTWO_AVR)
44 #define REAR_LOGIC_PIN 6
45 #elif defined(REELTWO_RP2040)
46 #define REAR_LOGIC_PIN 33
47 #define REAR_LOGIC_CLOCK_PIN 32
49 #define REAR_LOGIC_PIN 33
50 #define REAR_LOGIC_CLOCK_PIN 32
52 #error Unsupported platform
117 static constexpr
byte LEIA = 3;
129 static constexpr
byte TEXT = 15;
136 static constexpr
byte FIRE = 22;
163 (
long int)seq * 10000L +
164 (
long int)colorVal * 1000L +
165 (
long int)speedScale * 100 +
186 long defaultEffect = 0) :
211 template <
template<u
int8_t DATA_PIN, EOrder RGB_ORDER>
class CHIPSET, uint8_t DATA_PIN,
213 unsigned _count = 1,
unsigned _start = 0,
unsigned _end = 1,
unsigned _width = 1,
unsigned _height = 1>
217 template <LEDChipset CHIPSET, uint8_t DATA_PIN,
218 unsigned _count = 1,
unsigned _start = 0,
unsigned _end = 1,
unsigned _width = 1,
unsigned _height = 1>
219 class FastLEDPCB :
private Adafruit_NeoPixel
225 static const int count = _count;
226 static const int start = _start;
227 static const int end = _end;
228 static const int width = _width;
229 static const int height = _height;
234 FastLED.addLeds<CHIPSET, DATA_PIN, GRB>(fLED, count);
235 fill_solid(fLED, _count, CRGB(0,0,0));
236 #elif USE_LEDLIB == 1
239 numBytes = count * 3;
240 pixels = (uint8_t*)&fLED;
241 memset(fLED,
'\0',
sizeof(fLED));
253 Adafruit_NeoPixel::show();
263 template <ESPIChipsets CHIPSET, uint8_t DATA_PIN, uint8_t CLOCK_PIN, EOrder RGB_ORDER,
265 unsigned _count,
unsigned _start,
unsigned _end,
unsigned _width,
unsigned _height>
266 class FastLEDPCBClock
269 static const int count = _count;
270 static const int start = _start;
271 static const int end = _end;
272 static const int width = _width;
273 static const int height = _height;
277 FastLED.addLeds<CHIPSET, DATA_PIN, CLOCK_PIN, RGB_ORDER>(fLED, count);
278 fill_solid(fLED, _count, CRGB(0,0,0));
287 template <u
int8_t DATA_PIN = FRONT_LOGIC_PIN>
288 class LogicEngineFLDPCB0 :
public FastLEDPCB<WS2812B, DATA_PIN, 96, 8, 88, 8, 10>
291 static inline const byte* getLEDMap()
295 static const byte sLEDmap[] PROGMEM =
297 15,14,13,12,11,10, 9, 8,
298 16,17,18,19,20,21,22,23,
299 31,30,29,28,27,26,25,24,
300 32,33,34,35,36,37,38,39,
301 47,46,45,44,43,42,41,40,
302 88,89,90,91,92,93,94,95,
303 87,86,85,84,83,82,81,80,
304 72,73,74,75,76,77,78,79,
305 71,70,69,68,67,66,65,64,
306 56,57,58,59,60,61,62,63
313 template <u
int8_t DATA_PIN = FRONT_LOGIC_PIN>
314 class LogicEngineFLDPCB1 :
public FastLEDPCB<WS2812B, DATA_PIN, 80, 0, 80, 8, 10>
317 static inline const byte* getLEDMap()
321 static const byte sLEDmap[] PROGMEM =
323 0, 1, 2, 3, 4, 5, 6, 7,
324 15,14,13,12,11,10, 9, 8,
325 16,17,18,19,20,21,22,23,
326 31,30,29,28,27,26,25,24,
327 32,33,34,35,36,37,38,39,
328 79,78,77,76,75,74,73,72,
329 64,65,66,67,68,69,70,71,
330 63,62,61,60,59,58,57,56,
331 48,49,50,51,52,53,54,55,
332 47,46,45,44,43,42,41,40
339 template <u
int8_t DATA_PIN = FRONT_LOGIC_PIN>
340 class LogicEngineFLDPCB2 :
public FastLEDPCB<SK6812, DATA_PIN, 80, 0, 80, 8, 10>
343 static inline const byte* getLEDMap()
347 static const byte sLEDmap[] PROGMEM =
349 0, 1, 2, 3, 4, 5, 6, 7,
350 15,14,13,12,11,10, 9, 8,
351 16,17,18,19,20,21,22,23,
352 31,30,29,28,27,26,25,24,
353 32,33,34,35,36,37,38,39,
354 79,78,77,76,75,74,73,72,
355 64,65,66,67,68,69,70,71,
356 63,62,61,60,59,58,57,56,
357 48,49,50,51,52,53,54,55,
358 47,46,45,44,43,42,41,40
365 template <u
int8_t DATA_PIN = FRONT_LOGIC_PIN>
366 class LogicEngineFLDPCB2Inverted :
public FastLEDPCB<SK6812, DATA_PIN, 80, 0, 80, 8, 10>
369 static inline const byte* getLEDMap()
373 static const byte sLEDmap[] PROGMEM =
375 40,41,42,43,44,45,46,47,
376 55,54,53,52,51,50,49,48,
377 56,57,58,59,60,61,62,63,
378 71,70,69,68,67,66,65,64,
379 72,73,74,75,76,77,78,79,
380 39,38,37,36,35,34,33,32,
381 24,25,26,27,28,29,30,31,
382 23,22,21,20,19,18,17,16,
383 8, 9,10,11,12,13,14,15,
384 7, 6, 5, 4, 3, 2, 1, 0
391 template <u
int8_t DATA_PIN = FRONT_LOGIC_PIN>
392 class AstroPixelFLDPCB0 :
public FastLEDPCB<WS2812B, DATA_PIN, 90, 0, 90, 9, 10>
395 static inline const byte* getLEDMap()
399 static const byte sLEDmap[] PROGMEM =
401 0, 1, 2, 3, 4, 5, 6, 7, 8,
402 17,16,15,14,13,12,11,10, 9,
403 18,19,20,21,22,23,24,25,26,
404 35,34,33,32,31,30,29,28,27,
405 36,37,38,39,40,41,42,43,44,
406 45,46,47,48,49,50,51,52,53,
407 62,61,60,59,58,57,56,55,54,
408 63,64,65,66,67,68,69,70,71,
409 80,79,78,77,76,75,74,73,72,
410 81,82,83,84,85,86,87,88,89
416 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
417 class LogicEngineRLDPCB0 :
public FastLEDPCB<WS2812B, DATA_PIN, 80, 0, 80, 16, 4>
420 static inline const byte* getLEDMap()
424 static const byte sLEDmap[] PROGMEM =
426 0, 1, 2, 3, 4, 5, 6, 7, 48,49,50,51,52,53,54,55,
427 15,14,13,12,11,10, 9, 8, 63,62,61,60,59,58,57,56,
428 16,17,18,19,20,21,22,23, 64,65,66,67,68,69,70,71,
429 31,30,29,28,27,26,25,24, 79,78,77,76,75,74,73,72,
430 32,33,34,35,36,37,38,39, 80,81,82,83,84,85,86,87,
431 47,46,45,44,43,42,41,40, 95,94,93,92,91,90,89,88
438 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
439 class LogicEngineRLDPCBSUPER :
public FastLEDPCB<WS2812B, DATA_PIN, 256, 0, 255, 32, 8>
442 static inline const byte* getLEDMap()
444 static const byte sLEDmap[] PROGMEM =
446 0, 15, 16, 31, 32, 47, 48, 63, 64, 79, 80, 95, 96,111,112,127,128,143,144,159,160,175,176,191,192,207,208,223,224,239,240,255,
447 1, 14, 17, 30, 33, 46, 49, 62, 65, 78, 81, 94, 97,110,113,126,129,142,145,158,161,174,177,190,193,206,209,222,225,238,241,254,
448 2, 13, 18, 29, 34, 45, 50, 61, 66, 77, 82, 93, 98,109,114,125,130,141,146,157,162,173,178,189,194,205,210,221,226,237,242,253,
449 3, 12, 19, 28, 35, 44, 51, 60, 67, 76, 83, 92, 99,108,115,124,131,140,147,156,163,172,179,188,195,204,211,220,227,236,243,252,
450 4, 11, 20, 27, 36, 43, 52, 59, 68, 75, 84, 91,100,107,116,123,132,139,148,155,164,171,180,187,196,203,212,219,228,235,244,251,
451 5, 10, 21, 26, 37, 42, 53, 58, 69, 74, 85, 90,101,106,117,122,133,138,149,154,165,170,181,186,197,202,213,218,229,234,245,250,
452 6, 9, 22, 25, 38, 41, 54, 57, 70, 73, 86, 89,102,105,118,121,134,137,150,153,166,169,182,185,198,201,214,217,230,233,246,249,
453 7, 8, 23, 24, 39, 40, 55, 56, 71, 72, 87, 88,103,104,119,120,135,136,151,152,167,168,183,184,199,200,215,216,231,232,247,248
460 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
461 class LogicEngineRLDPCB1 :
public FastLEDPCB<WS2812B, DATA_PIN, 96, 0, 96, 24, 4>
464 static inline const byte* getLEDMap()
467 static const byte sLEDmap[] PROGMEM =
469 0, 1, 2,28, 3,27, 4,26, 5,25, 6, 7, 8, 9,22,10,21,11,20,12,19,13,14,15,
470 31,30,29,32,33,34,35,36,37,38,39,24,23,40,41,42,43,44,45,46,47,18,17,16,
471 64,65,66,63,62,61,60,59,58,57,56,71,72,55,54,53,52,51,50,49,48,77,78,79,
472 95,94,93,67,92,68,91,69,90,70,89,88,87,86,73,85,74,84,75,83,76,82,81,80
479 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
480 class LogicEngineRLDPCB2 :
public FastLEDPCB<SK6812, DATA_PIN, 96, 0, 96, 24, 4>
483 static inline const byte* getLEDMap()
486 static const byte sLEDmap[] PROGMEM =
488 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,
489 47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,
490 48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,
491 95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72
498 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
499 class LogicEngineRLDPCB2Inverted :
public FastLEDPCB<SK6812, DATA_PIN, 96, 0, 96, 24, 4>
502 static inline const byte* getLEDMap()
506 static const byte sLEDmap[] PROGMEM =
508 72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,
509 71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,
510 24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
511 23,22,21,20,19,18,17,16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
518 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
519 class AstroPixelRLDPCB0 :
public FastLEDPCB<WS2812B, DATA_PIN, 108, 0, 108, 27, 4>
522 static inline const byte* getLEDMap()
525 static const byte sLEDmap[] PROGMEM =
527 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,
528 53, 52, 51, 50, 49, 48, 47, 46, 45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,
529 54, 55, 56, 57, 58, 59, 60, 61, 62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,
530 107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81
537 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN, u
int8_t CLOCK_PIN = REAR_LOGIC_CLOCK_PIN>
539 class LogicEngineRLDPCB3 :
public FastLEDPCBClock<SK9822, DATA_PIN, CLOCK_PIN, BGR, 112, 0, 112, 28, 4>
542 static inline const byte* getLEDMap()
545 static const byte sLEDmap[] PROGMEM =
547 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
548 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28,
549 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
550 111,110,109,108,107,106,105, 104,103,102,101,100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84
557 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN, u
int8_t CLOCK_PIN = REAR_LOGIC_CLOCK_PIN>
558 class LogicEngineRLDPCB3Inverted :
public FastLEDPCBClock<SK9822, DATA_PIN, CLOCK_PIN, BGR, 112, 0, 112, 28, 4>
561 static inline const byte* getLEDMap()
565 static const byte sLEDmap[] PROGMEM =
567 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100,101,102,103,104, 105,106,107,108,109,110,111,
568 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56,
569 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
570 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
602 typedef const char* (*LogicMessageSelector)(
unsigned index);
604 typedef byte (*
LogicRenderGlyph)(
char ch,
byte fontNum,
const CRGB fontColors[],
int x,
int y, CRGB* leds,
const byte* ledMap,
int w,
int h,
byte* glyphHeight);
613 fDisplayEffectVal = inputNum;
618 selectEffect(sequence(seq, colorVal, speedScale, numSeconds));
623 setTextMessage(text);
624 selectEffect(sequence(TEXT, colorVal, speedScale, numSeconds));
629 setTextMessage(text);
630 selectEffect(sequence(TEXTSCROLLLEFT, colorVal, speedScale, numSeconds));
635 setTextMessage(text);
636 selectEffect(sequence(TEXTSCROLLRIGHT, colorVal, speedScale, numSeconds));
641 setTextMessage(text);
642 selectEffect(sequence(TEXTSCROLLUP, colorVal, speedScale, numSeconds));
647 int length = strlen(cmd);
648 if (*cmd++ ==
'L' && *cmd++ ==
'E')
650 long int cmdvalue = 0;
655 unsigned reqId = *c++ -
'0';
656 if (reqId != getID()) {
660 while (*c >=
'0' && *c <=
'9')
662 cmdvalue = cmdvalue * 10 + (*c++ -
'0');
664 selectEffect(cmdvalue);
671 calculateAllColors(fSettings.fPalNum, fSettings.fBri);
672 for (
unsigned i = 0; i < count(); i++)
674 unsigned index = mapLED(i);
675 LEDStatus* ledStatus = &fLEDStatus[index];
676 ledStatus->
fColorNum = random8(fTotalColorsWBIZ);
678 updateMappedLED(index, fSettings.fHue);
680 fStatusMillis = millis();
681 fDisplayEffectVal = fSettings.fDefaultEffect;
686 uint32_t currentMillis = millis();
687 if (fLastMillis + 10L > currentMillis)
689 fLastMillis = currentMillis;
690 if (currentMillis - fStatusMillis >= fStatusDelay)
692 fStatusMillis = currentMillis;
693 fFlipFlop = !fFlipFlop;
695 int selectSequence = (fDisplayEffectVal % 100000000L) / 10000L;
696 int selectLength = (fDisplayEffectVal % 100);
699 if (hasEffectChanged())
701 setEffectObject(NULL);
703 calculateAllColors(fSettings.fPalNum, fSettings.fBri);
704 fStatusDelay = getDefaultEffectDelay();
705 fEffectStartMillis = currentMillis;
706 if (fEffectSelector != NULL)
708 fLogicEffect = fEffectSelector(selectSequence);
711 fEffectMillis = currentMillis - fEffectStartMillis;
713 bool continueEffect = (fLogicEffect != NULL) ? fLogicEffect(*
this) :
false;
714 fPreviousEffectVal = fDisplayEffectVal;
715 if (!continueEffect || (selectLength > 0 &&
unsigned(selectLength) * 1000L < fEffectMillis))
717 if (selectSequence == RANDOM)
720 fPreviousEffectVal = ~fDisplayEffectVal;
724 selectEffect(fSettings.fDefaultEffect);
727 fPreviousEffect = fDisplayEffect;
730 #elif USE_LEDLIB == 1
739 return (fPreviousEffectVal != fDisplayEffectVal);
743 fPreviousEffectVal = ~fDisplayEffectVal;
748 return (fPreviousEffect != fDisplayEffect);
764 int selectColor = (fDisplayEffectVal % 10000) / 1000;
770 return mapSelectColorToHue(getEffectColor());
775 int selectSpeed = (fDisplayEffectVal % 1000) / 100;
781 int selectLength = (fDisplayEffectVal % 100);
787 int selectTextMsg = (fDisplayEffectVal % 100000000) / 10000000;
788 return selectTextMsg;
793 return fEffectMillis;
798 return fSettings.fHue;
803 fSettings.fHue = hue;
808 return fSettings.fFade;
813 fSettings.fFade = fade;
818 return fSettings.fDelay;
823 fSettings.fDelay = delay;
828 return fSettings.fBri;
833 fSettings.fBri = bri;
848 return fEffectObject;
858 if (fEffectObject != NULL)
859 delete fEffectObject;
880 fEffectRange = max(min(1.0f, percent), 0.0f);
885 return fEffectMsgWidth;
890 return fEffectMsgHeight;
895 return (fPeakSource != NULL) ? fPeakSource->getPeakValue() : 0;
905 fStatusDelay = effectDelay;
925 return pgm_read_byte(&fLEDMap[index]);
930 fEffectSelector = selector;
935 fMessageSelector = selector;
940 fPMessageSelector = selector;
945 fPeakSource = &provider;
948 void set(
unsigned index,
const struct CRGB& val)
950 fLED[pgm_read_byte(&fLEDMap[fLEDStart + index])] = val;
953 void setHSV(
unsigned index, uint8_t hue, uint8_t sat, uint8_t val)
955 fLED[pgm_read_byte(&fLEDMap[fLEDStart + index])].setHSV(hue, sat, val);
965 if (++fSettings.fPalNum == PAL_COUNT)
966 fSettings.fPalNum = 0;
967 calculateAllColors(fSettings.fPalNum, fSettings.fBri);
972 return fSettings.fPalNum;
977 fSettings.fPalNum = palNum;
978 fSettings.fHue = hue;
979 calculateAllColors(fSettings.fPalNum, fSettings.fBri);
984 int blackX = int(fEffectRange * width());
985 if (blackX < width())
987 CRGB blackColor = { 0, 0, 0 };
988 for (
int x = blackX; x < width(); x++)
990 for (
int y = 0; y < height(); y++)
992 fLED[pgm_read_byte(&fLEDMap[y * width() + x])] = blackColor;
1000 updateDisplay(fSettings.fBri);
1005 updateDisplay((fPeakSource != NULL) ? fPeakSource->getPeakValue() : fSettings.fBri);
1010 for (
unsigned i = fLEDStart; i < fLEDEnd; i++)
1011 updateMappedLED(mapLED(i), fSettings.fHue, bri);
1012 clearBlockedPortion();
1017 for (
unsigned i = fLEDStart; i < count() / 2; i++)
1018 updateMappedLED(mapLED(i), fSettings.fHue, topBri);
1019 for (
unsigned i = count() / 2; i < fLEDEnd; i++)
1020 updateMappedLED(mapLED(i), fSettings.fHue, bottomBri);
1021 clearBlockedPortion();
1026 if (width() % 3 == 0)
1030 unsigned index = fLEDStart;
1031 unsigned third = width() / 3;
1032 for (
byte row = 0; row < height() * 3; row++)
1034 for (
byte col = 0; col < third && index < fLEDEnd; col++, index++)
1035 updateMappedLED(mapLED(index), fSettings.fHue, (!flip) ? topBri : bottomBri);
1042 for (
unsigned i = fLEDStart; i < count() / 2; i++)
1043 updateMappedLED(mapLED(i), fSettings.fHue, topBri);
1044 for (
unsigned i = count() / 2; i < fLEDEnd; i++)
1045 updateMappedLED(mapLED(i), fSettings.fHue, bottomBri);
1047 clearBlockedPortion();
1055 byte glyphHeight = 0;
1058 fRenderGlyph(
' ', fEffectFontNum, NULL, 0, 0, NULL, NULL, 0, 0, &glyphHeight);
1059 while ((ch = *txt++) !=
'\0')
1064 outWidth = max(outWidth, textWidth);
1065 outHeight += glyphHeight;
1069 textWidth += fRenderGlyph(ch, fEffectFontNum, NULL, 0, 0, NULL, NULL, 0, 0, NULL);
1071 outWidth = max(outWidth, textWidth);
1072 outHeight = (outWidth > 0) ? outHeight + glyphHeight : 0;
1081 byte glyphHeight = 0;
1082 const char* txt = (
const char*)ptxt;
1085 fRenderGlyph(
' ', fEffectFontNum, NULL, 0, 0, NULL, NULL, 0, 0, &glyphHeight);
1086 while ((ch = pgm_read_byte(txt++)) !=
'\0')
1091 outWidth = max(outWidth, textWidth);
1092 outHeight += glyphHeight;
1096 textWidth += fRenderGlyph(ch, fEffectFontNum, NULL, 0, 0, NULL, NULL, 0, 0, NULL);
1098 outWidth = max(outWidth, textWidth);
1099 outHeight = (outWidth > 0) ? outHeight + glyphHeight : 0;
1105 return fEffectFontNum;
1110 fEffectFontNum = fontNum;
1112 if (fEffectMsgText != NULL)
1114 fEffectMsgLen = measureText(fEffectMsgText, fEffectMsgWidth, fEffectMsgHeight);
1116 else if (fEffectMsgTextP != NULL)
1118 fEffectMsgLen = measureText(fEffectMsgTextP, fEffectMsgWidth, fEffectMsgHeight);
1124 fEffectMsgLen = fEffectMsgWidth = 0;
1125 fEffectMsgText = msg;
1126 fEffectMsgTextP = NULL;
1127 if (fEffectMsgText != NULL)
1128 fEffectMsgLen = measureText(fEffectMsgText, fEffectMsgWidth, fEffectMsgHeight);
1133 fEffectMsgLen = fEffectMsgWidth = 0;
1134 if (selectTextMsg != 0)
1137 fEffectMsgTextP = (fPMessageSelector != NULL) ? fPMessageSelector(selectTextMsg) : NULL;
1138 if (fEffectMsgTextP == NULL)
1139 fEffectMsgText = (fMessageSelector != NULL) ? fMessageSelector(selectTextMsg) : NULL;
1140 if (fEffectMsgTextP == NULL && fEffectMsgText == NULL)
1141 fEffectMsgTextP = F(
"STAR WARS");
1143 if (fEffectMsgText != NULL)
1145 fEffectMsgLen = measureText(fEffectMsgText, fEffectMsgWidth, fEffectMsgHeight);
1147 else if (fEffectMsgTextP != NULL)
1149 fEffectMsgLen = measureText(fEffectMsgTextP, fEffectMsgWidth, fEffectMsgHeight);
1156 fill_solid(fLED, count(), CRGB(0,0,0));
1157 #elif USE_LEDLIB == 1
1158 int numToFill = count();
1160 CRGB color = CRGB(0, 0, 0);
1161 for (
int i = 0; i < numToFill; i++)
1170 byte hue = fAllColors[0].h + effectHue;
1171 byte sat = fAllColors[0].s;
1172 fontColors[0].setHSV(hue, sat, 1);
1173 fontColors[1].setHSV(hue, sat, 16);
1174 fontColors[2].setHSV(hue, sat, 64);
1177 for (
int i = 0; i < fEffectMsgLen; i++)
1180 if (fEffectMsgText != NULL)
1181 ch = fEffectMsgText[i];
1182 if (fEffectMsgTextP != NULL)
1183 ch = pgm_read_byte(&((
const char*)fEffectMsgTextP)[i]);
1189 else if (x < width())
1191 int adv = fRenderGlyph(ch, fEffectFontNum, fontColors, x, y, fLED, fLEDMap, fWidth, fHeight, NULL);
1211 if (
unsigned(x) <
unsigned(fEffectRange * width()) &&
unsigned(y) <
unsigned(height()))
1213 fLED[pgm_read_byte(&fLEDMap[y * width() + x])].setHSV(
1214 fAllColors[0].h + effectHue, fAllColors[0].s, bri);
1220 if (
unsigned(x) <
unsigned(fEffectRange * width()) &&
unsigned(y) <
unsigned(height()))
1222 fLED[pgm_read_byte(&fLEDMap[y * width() + x])] = val;
1229 color.r = (r / 255.0) * MAX_BRIGHTNESS / 2;
1230 color.g = (g / 255.0) * MAX_BRIGHTNESS / 2;
1231 color.b = (b / 255.0) * MAX_BRIGHTNESS / 2;
1232 setPixelRGB(x, y, color);
1243 static const HSVColor keyColors[PAL_COUNT][4] PROGMEM = {
1244 { {170, 255, 0} , {170, 255, 85} , {170, 255, 170} , {170, 0, 170} } ,
1245 { { 90, 235, 0} , { 75, 255, 250} , { 30, 255, 184} , { 0, 255, 250} } ,
1246 { { 0, 255, 0} , { 0, 255, 0} , { 0, 255, 100} , { 0, 255, 250} } ,
1247 { { 0, 255, 0} , { 0, 255, 250} , { 40, 255, 0} , { 40, 255, 250} } ,
1248 { {165, 50, 248} , {166, 181, 226} , {165, 223, 89} , {255, 255, 214} } ,
1249 { {87, 206, 105} , { 79, 255, 214} , { 43, 255, 250} , { 25, 255, 214} }
1253 for (
byte kcol = 0; kcol < 4; kcol++)
1256 const HSVColor* wc = &keyColors[colorPalNum][kcol];
1257 HSVColor workColor = {
1258 pgm_read_byte(&wc->h),
1259 pgm_read_byte(&wc->s),
1260 pgm_read_byte(&wc->v)
1262 byte tnum = kcol + fTweens * kcol;
1263 HSVColor* tc = &fAllColors[tnum];
1264 tc->h = workColor.h;
1265 tc->s = workColor.s;
1267 brightVal = min(brightVal, (
byte)MAX_BRIGHTNESS);
1268 tc->v = map8(workColor.v, MIN_BRIGHTNESS, brightVal);
1269 if (tnum + 1 != fTotalColors)
1271 const HSVColor* hsvptr = &keyColors[colorPalNum][kcol + 1];
1272 for (
byte el = 0; el < 3; el++)
1275 int perStep = int(pgm_read_byte(&hsvptr->c[el]) - workColor.c[el]) / (fTweens + 1);
1278 for (
byte tweenCount = 1; tweenCount <= fTweens; tweenCount++)
1280 byte val = workColor.c[el] + tweenCount * perStep;
1281 tc[tweenCount].c[el] = (el == 2) ?
1282 map8(val, MIN_BRIGHTNESS, brightVal) : val;
1288 for (
byte tweenCount = 1; tweenCount <= fTweens; tweenCount++)
1290 tc[tweenCount].c[el] = (el == 2) ?
1291 map8(workColor.c[el], MIN_BRIGHTNESS, brightVal) : workColor.c[el];
1301 calculateAllColors(fSettings.fPalNum, fSettings.fBri);
1306 LEDStatus* ledStatus = &fLEDStatus[index];
1314 if (ledStatus->
fColorNum >= fTotalColorsWBIZ)
1316 byte realColor = actualColorNum(ledStatus->
fColorNum);
1319 random8(fSettings.fDelay) :
1322 HSVColor* myColor = &fAllColors[realColor];
1323 fLED[index].setHSV(myColor->h + hueVal, myColor->s,
1324 (briVal == 255) ? myColor->v : map8(briVal, 0, myColor->v));
1335 selectEffect(NORMVAL);
1341 fSettings.fFade = arg;
1344 fSettings.fDelay = arg;
1347 fSettings.fHue = arg;
1350 fSettings.fBri = arg;
1351 calculateAllColors();
1373 if (++fSettings.fPalNum >= PAL_COUNT)
1374 fSettings.fPalNum = 0;
1375 calculateAllColors();
1381 selectSequence(RANDOM);
1385 fDisplayEffectVal = (fDisplayEffectVal / 100) * 100 + arg;
1388 selectEffect(TEXTSCROLLLEFT);
1398 setTextMessage(arg);
1410 fSettings = newSettings;
1417 static const byte sEffectHue[] PROGMEM = {
1418 0,0,26,42,85,128,170,202,213,228
1420 return (selectColor <
SizeOfArray(sEffectHue)) ? pgm_read_byte(&sEffectHue[selectColor]) : 0;
1440 byte totalColorsWBIZ,
1447 HSVColor* allColors,
1451 fID((id == 0) ? getNextID() : id),
1458 fTotalColors(totalColors),
1459 fTotalColorsWBIZ(totalColorsWBIZ),
1461 fAllColors(allColors),
1462 fLEDStatus(ledStatus),
1464 fRenderGlyph(renderGlyph)
1476 setJawaAddress(addr);
1480 virtual void show() = 0;
1483 virtual void defaultSettings() = 0;
1487 LogicMessageSelector fMessageSelector = NULL;
1488 LogicPMessageSelector fPMessageSelector = NULL;
1501 byte fTotalColorsWBIZ;
1503 HSVColor* fAllColors;
1505 const byte* fLEDMap;
1506 byte fMaxBrightness = MAX_BRIGHTNESS;
1508 byte fDisplayEffect = 0;
1509 byte fPreviousEffect = ~0;
1511 uint32_t fLastMillis = 0;
1512 uint32_t fStatusMillis = 0;
1513 uint32_t fStatusDelay = 0;
1514 bool fFlipFlop =
false;
1516 long fDisplayEffectVal = NORMVAL;
1517 long fPreviousEffectVal = ~fDisplayEffectVal;
1518 uint32_t fEffectStartMillis = 0;
1519 unsigned int fEffectMillis = 0;
1524 uint32_t fEffectData = 0;
1525 uint32_t fEffectData2 = 0;
1526 float fEffectRange = 1.0;
1527 int fEffectMsgStartX;
1529 int fEffectMsgWidth;
1530 int fEffectMsgHeight;
1531 bool fEffectMsgTransition;
1532 byte fEffectFontNum = 0;
1533 const char* fEffectMsgText = NULL;
1537 inline int actualColorNum(
int x)
const
1539 return (x >= fTotalColors) ? (fTotalColors - 2) - (x - fTotalColors) : x;
1554 template <
typename PCB, LogicRenderGlyph renderGlyph,
byte TWEENS = 14>
1574 fDefaults(&defaults)
1582 virtual void show()
override
1588 virtual void defaultSettings()
override
1590 fSettings = *fDefaults;
1595 fSettings = *fDefaults = settings;
1598 static const unsigned TOTALCOLORS = (4 + (TWEENS * 3));
1599 static const unsigned TOTALCOLORSWBIZ = ((TOTALCOLORS * 2) - 2);
1603 HSVColor fAllColorsStorage[TOTALCOLORS];
1663 r.
setHue(60 + map(peakVal,0,100,0,20));
1687 static const unsigned int sMarchSegment[] =
1699 for (
byte i = 1; i <
SizeOfArray(sMarchSegment); i++)
1701 if (effectMillis > sMarchSegment[i-1] && effectMillis < sMarchSegment[i])
1716 return (effectMillis < 48300);
1734 if (effectMillis > 1800 && effectMillis < 6000)
1739 else if (effectMillis > 6000 && effectMillis < 8000)
1744 r.
setBrightness(map(effectMillis - 6000, 2000, 0 , 0, 255));
1748 return (effectMillis < 18000);
1813 r.
setHue(effectHue - 128);
1817 r.
setHue(effectHue + 128);
1834 if (effectColor == r.
kRed) altColor = r.
kBlue;
1835 else if (effectColor == r.
kBlue) altColor = r.
kRed;
1841 else if (effectColor == r.
kPink) altColor = r.
kBlue;
1859 for (y = 0; y < r.
height(); y++)
1862 x += (!dir) ? 1 : -1;
1879 else if (random(100) <= 5)
1887 r.
setEffectData((uint32_t(dir)<<16L) | ((uint32_t(px)<<8L)) | x);
1944 if (peakVal < speedVal)
2127 int x = int(xy >> 16);
2128 int y = int(xy & 0xFFFFL);
2133 for (x = 0; x < r.
width(); x++)
2142 r.
setEffectData((uint32_t(x)<<16L) | ((uint32_t(y)&0XFFFF)));
2172 for (x = 0; x < r.
width(); x++)
2174 for (x = 0; x < r.
width(); x++)
2177 y += (!dir) ? 1 : -1;
2188 r.
setEffectData((uint32_t(dir)<<16L) | ((uint32_t(py)<<8L)) | y);
2218 for (y = 0; y < r.
height(); y++)
2220 for (y = 0; y < r.
height(); y++)
2223 x += (!dir) ? 1 : -1;
2234 r.
setEffectData((uint32_t(dir)<<16L) | ((uint32_t(px)<<8L)) | x);
2244 static const unsigned char sValueMask[10][24] PROGMEM = {
2245 {32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 , 32 , 0 , 0 , 0 , 0 , 0 , 0 , 32, 32 , 0 , 0 , 0 , 0 , 0 , 0 , 32 },
2246 {64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 , 64 , 0 , 0 , 0 , 0 , 0 , 0 , 64, 64 , 0 , 0 , 0 , 0 , 0 , 0 , 64 },
2247 {96 , 32 , 0 , 0 , 0 , 0 , 32 , 96 , 96 , 32 , 0 , 0 , 0 , 0 , 32 , 96, 32 , 0 , 0 , 0 , 0 , 0 , 32 , 96 },
2248 {128, 64 , 32 , 0 , 0 , 32 , 64 , 128, 128, 64 , 32 , 0 , 0 , 32 , 64 , 128, 64 , 32 , 0 , 0 , 0 , 32 , 64 , 128},
2249 {160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 160},
2250 {160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 96 , 64 , 32 , 32 , 64 , 96 , 160, 160},
2251 {192, 128, 96 , 64 , 64 , 96 , 128, 192, 192, 128, 96 , 64 , 64 , 96 , 128, 192, 192, 128 , 96 , 64 , 64 , 96 , 128, 192},
2252 {255, 160, 128, 96 , 96 , 128, 160, 255, 255, 160, 128, 96 , 96 , 128, 160, 255, 255, 160 , 128, 96 , 96 , 128, 160, 255},
2253 {255, 192, 160, 128, 128, 160, 192, 255, 255, 192, 160, 128, 128, 160, 192, 255, 255, 192 , 160, 128 ,128 , 160, 192, 255},
2254 {255, 192, 160, 128, 128, 160, 192, 255, 255, 192, 160, 128, 128, 160, 192, 255, 255, 192 , 160, 128 ,128 , 160, 192, 255},
2257 static const unsigned char sHueMask[10][24] PROGMEM = {
2258 {1 , 11, 19, 25, 25, 22, 11, 1 , 1 , 11, 19, 25, 25, 22, 11, 1, 1 , 1 , 11, 19, 25, 25, 22, 11 },
2259 {1 , 8 , 13, 19, 25, 19, 8 , 1 , 1 , 8 , 13, 19, 25, 19, 8 , 1, 1 , 1 , 8 , 13, 19, 25, 19, 8 },
2260 {1 , 8 , 13, 16, 19, 16, 8 , 1 , 1 , 8 , 13, 16, 19, 16, 8 , 1, 1 , 1 , 8 , 13, 16, 19, 16, 8 },
2261 {1 , 5 , 11, 13, 13, 13, 5 , 1 , 1 , 5 , 11, 13, 13, 13, 5 , 1, 1 , 1 , 5 , 11, 13, 13, 13, 5 },
2262 {1 , 5 , 11, 11, 11, 11, 5 , 1 , 1 , 5 , 11, 11, 11, 11, 5 , 1, 1 , 1 , 5 , 11, 11, 11, 11, 5 },
2263 {1 , 5 , 11, 11, 11, 11, 5 , 1 , 1 , 5 , 11, 11, 11, 11, 5 , 1, 1 , 1 , 5 , 11, 11, 11, 11, 5 },
2264 {0 , 1 , 5 , 8 , 8 , 5 , 1 , 0 , 0 , 1 , 5 , 8 , 8 , 5 , 1 , 0, 0 , 1 , 5 , 8 , 8 , 5 , 1 , 0 },
2265 {0 , 0 , 1 , 5 , 5 , 1 , 0 , 0 , 0 , 0 , 1 , 5 , 5 , 1 , 0 , 0, 0 , 0 , 1 , 5 , 5 , 1 , 0 , 0 },
2266 {0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0, 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 },
2267 {0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0, 0 , 0 , 0 , 1 , 1 , 0 , 0 , 0 },
2270 int count = r.
count();
2271 int width = r.
width();
2283 for (
int i = 0; i < count; i++)
2289 for (uint8_t x = 0; x < width; x++)
2300 for (uint8_t y = height - 1; y > 0; y--)
2302 for (uint8_t x = 0; x < width; x++)
2307 for (uint8_t x = 0; x < width; x++)
2312 for (uint8_t x = 0; x < width; x++)
2320 int heightm1 = height - 1;
2321 for (
byte y = heightm1; y > 0; y--)
2323 for (
byte x = 0; x < width; x++)
2325 nextv = (((100.0-pcnt) * ledStatus[r.
mapLED(y*width+x)].fColorNum +
2326 pcnt * ledStatus[r.
mapLED((y-1)*width+x)].fColorNum) / 100.0) - pgm_read_byte(&sValueMask[y][x]);
2327 leds[r.
mapLED((heightm1-y)*width+x)].setHSV(pgm_read_byte(&sHueMask[y][x]), 255, (uint8_t)max(0, nextv));
2332 for (
byte x = 0; x < width; x++)
2334 leds[r.
mapLED(heightm1*width+x)].setHSV(pgm_read_byte(&sHueMask[0][x]), 255,
2335 (uint8_t)(((100.0-pcnt) * ledStatus[r.
mapLED(x)].fColorNum + pcnt * ledStatus[x].fColorPause)/100.0));
2374 float xmid = r.
width()/2;
2375 float ymid = r.
height()/2;
2382 for (dy = 0; dy < r.
height(); dy++) {
2383 for (dx = 0; dx < r.
width(); dx++) {
2384 if ((dy+px >= ymid && dy-px <= ymid) && (dx+px >= xmid && dx-px <= xmid))
2392 px += (!dir) ? 1 : -1;
2393 if (px > r.
width()/2 || px < 1) {
2396 r.
setEffectData((uint32_t(dir)<<16L) | ((uint32_t(px)<<8L)) | x);
2412 LogicSolidColorEffect,
2414 LogicFlipFlopEffect,
2415 LogicFlipFlopAltEffect,
2416 LogicColorSwapEffect,
2418 LogicRedAlertEffect,
2419 LogicMicBrightEffect,
2420 LogicMicRainbowEffect,
2421 LogicLightsOutEffect,
2423 LogicTextScrollLeftEffect,
2424 LogicTextScrollRightEffect,
2425 LogicTextScrollUpEffect,
2426 LogicRoamingPixelEffect,
2427 LogicHorizontalScanLineEffect,
2428 LogicVerticalScanLineEffect,
2430 LogicPSIColorWipeEffect,
2434 selectSequence = random(
SizeOfArray(sLogicEffects));
2437 return LogicEffect(sLogicEffects[selectSequence]);
2448 for (
int i = 0; i < 8; i++)
2460 template <LogicStaggerType staggerType>
2461 byte LogicRenderGlyph4Pt(
char ch,
byte fontNum,
const CRGB fontColors[],
int x,
int y, CRGB* leds,
const byte* ledMap,
int w,
int h,
byte* outGlyphHeight)
2466 byte dstRowBytes = w;
2469 byte glyphHeight = 4;
2470 byte glyphBitmap[2*8];
2472 bool found = font->
getLetter(ch, glyphBitmap, glyphRowBytes, advance);
2476 if (ch >=
'a' && ch <
'z')
2477 found = font->
getLetter(
'A'+(ch-
'a'), glyphBitmap, glyphRowBytes, advance);
2479 else if (ch >=
'A' && ch <
'Z')
2480 found = font->
getLetter(
'a'+(ch-
'A'), glyphBitmap, glyphRowBytes, advance);
2482 if (outGlyphHeight != NULL)
2483 *outGlyphHeight = glyphHeight;
2486 y += glyphHeight - 1;
2487 while (glyphHeight > 0 && y >= 0)
2490 byte* s = &glyphBitmap[(y-starty) * glyphRowBytes];
2491 if (ledMap != NULL && y < dstHeight)
2493 for (
byte rb = 0; rb < glyphRowBytes; rb++)
2497 byte m = 0b11000000;
2499 while (adv > 0 && m != 0 && xx < dstWidth)
2501 if ((b & m) != 0 && xx >= 0)
2503 leds[pgm_read_byte(&ledMap[y * dstRowBytes + xx])] = fontColors[((b >> i) & 3)-1];
2519 static byte LogicRenderGlyph5Pt(
char ch,
byte fontNum,
const CRGB fontColors[],
int x,
int y, CRGB* leds,
const byte* ledMap,
int w,
int h,
byte* outGlyphHeight)
2521 byte dstRowBytes = w;
2522 byte glyphRowBytes = 1;
2523 byte glyphHeight = 5;
2524 byte glyphBitmap[2*8];
2526 bool found = font->
getLetter(ch, glyphBitmap);
2530 if (ch >=
'a' && ch <
'z')
2531 found = font->
getLetter(
'A'+(ch-
'a'), glyphBitmap);
2533 else if (ch >=
'A' && ch <
'Z')
2534 found = font->
getLetter(
'a'+(ch-
'A'), glyphBitmap);
2538 for (
int i = 0; i < glyphHeight; i++)
2540 byte b = glyphBitmap[i * glyphRowBytes];
2541 for (
byte i = 0; i < 8; i++)
2545 advance = max((
int)advance, 8-i);
2553 if (outGlyphHeight != NULL)
2554 *outGlyphHeight = glyphHeight;
2557 y += glyphHeight - 1;
2558 while (glyphHeight > 0 && y >= 0)
2561 byte* s = &glyphBitmap[(y-starty) * glyphRowBytes];
2562 if (ledMap != NULL && y < h)
2564 for (
byte rb = 0; rb < glyphRowBytes; rb++)
2568 byte m = 0b10000000;
2570 while (adv > 0 && m != 0 && xx < w)
2572 if ((b & m) != 0 && xx >= 0)
2574 leds[pgm_read_byte(&ledMap[y * dstRowBytes + xx])] = fontColors[2];
2606 template <u
int8_t DATA_PIN = FRONT_LOGIC_PIN>
2607 using AstroPixelFLD = LogicEngineDisplay<AstroPixelFLDPCB0<DATA_PIN>, LogicRenderGlyph5Pt>;
2619 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
2620 using AstroPixelRLD = LogicEngineDisplay<AstroPixelRLDPCB0<DATA_PIN>, LogicRenderGlyph4Pt<LogicStaggerType::kNone>>;
2632 template <u
int8_t DATA_PIN = FRONT_LOGIC_PIN>
2645 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
2646 using LogicEngineNabooRLD = LogicEngineDisplay<LogicEngineRLDPCB0<DATA_PIN>, LogicRenderGlyph4Pt<LogicStaggerType::kEven>>;
2659 template <u
int8_t DATA_PIN = FRONT_LOGIC_PIN>
2672 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
2673 using LogicEngineKennyRLD = LogicEngineDisplay<LogicEngineRLDPCB1<DATA_PIN>, LogicRenderGlyph4Pt<LogicStaggerType::kEven>>;
2674 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
2699 template <u
int8_t DATA_PIN = FRONT_LOGIC_PIN>
2713 template <u
int8_t DATA_PIN = FRONT_LOGIC_PIN>
2727 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
2740 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
2753 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
2766 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN>
2780 template <u
int8_t DATA_PIN = FRONT_LOGIC_PIN>
2794 template <u
int8_t DATA_PIN = FRONT_LOGIC_PIN>
2809 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN, u
int8_t CLOCK_PIN = REAR_LOGIC_CLOCK_PIN>
2810 using LogicEngineCurvedRLD = LogicEngineDisplay<LogicEngineRLDPCB3<DATA_PIN, CLOCK_PIN>, LogicRenderGlyph4Pt<LogicStaggerType::kNone>>;
2822 template <u
int8_t DATA_PIN = REAR_LOGIC_PIN, u
int8_t CLOCK_PIN = REAR_LOGIC_CLOCK_PIN>