-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathPSIPro.ino
2614 lines (2388 loc) · 81.7 KB
/
PSIPro.ino
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
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
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
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**********************************************************************************************************
* Maxstang's MaxPSI Sketch for the PSI PRO Connected
* Written by Neil Hutchison
* Main sequence transitions by Krijn Schaap, based on his PSI sketch. Many thanks Krijn.
* Pattern Timing Tuning by Malcolm MacKenzie
* Bug fixes and Mini support by Skelmir
*
*
* Thanks to Malcolm (Maxstang) for the boards, support, testing and encouragement.
*
*
*
* BEFORE BUILDING OR UPLOADING THIS SKETCH, be sure that the config.h and matrices.h files are in the skectch folder.
*
* Version 1.7
*
* Version History :
*
* Version 1.7 - 30th Dec 2020
*
* Fix a bug in the main loop restoring the default pattern
* Remove compiler warnings
* Support for Mini added.
*
* Version 1.6 - 14th May 2020
*
* Fixes for the Valid PSI address checks in the T command
* Check for a valid pattern number, and ignore if the pattern does not match a known pattern.
* Continue running the current pattern with the current timings.
*
* Version 1.5 - 13th May 2020
*
* Adding a check in the T command processing to prevent setting the global timing parameters if
* the command is not addressed to a PSI (address 0, 4,5)
*
* Version 1.3 - 21st April 2020
*
* Fixed a bug with the timing for Imperial March
*
* Version 1.2 - 16th April 2020
*
* Correct comment typos
* Always on was actually only on for 17 min. Changed to +18 hrs.
* Change Star Wars Intro
*
* Version 1.1 - 13th April 2020
*
* Fixed a bug in the Rebel pattern where it would blink the first time a timing command was given
* Subsequent calls to Rebel with timing supplied worked
* Explicitly check in Fade Out and Lightsaber Battle for a timing parameter supplied and ignore it
* All CRGB:White changed to CRGB:Grey to reduce power consumption of the panel
* Max Brightness allowed upped to 200 from 175
* Renamed the sketch to match git repo
*
* Version 1.0 - 11th April 2020
* Added 3Pyy command to set brightness without saving to EEPROM
* Limit the Max LED Brightness to 200 to preserve the LED Life.
*
* Version 0.99_5 - 10th April 2020
* Renamed USB_DEBUG to USB_SERIAL
*
* Version 0.99_4 - 10th April 2020
* Fixed the Command line setting for per pattern timeout that was added
* Timings over 32 seconds did not work
* To set the pattern as "always On" Set the timing parameter to 256 which will
* run the pattern for 16 hours - I'll call that good enough for always on!
* Added Firmware Average for the POT readings. This works around the issue of not
* having a resitor on the POT.
*
* Version 0.98 - 8th April 2020
* Added the ability for each sequence to run for a given time.
* Rather than try to set the time a pattern runs for by setting the loops, you can
* specify the total time the pattern should run for. To disable the total run time
* and use a set number of loops, set the run time parameter to 0.
* Added the ability to set the command duration in seconds via the command.
* This only applies to T commands.
* Send the command using 0Tx|y where |y is optional. y is in seconds.
*
* Version 0.97 - 7th April 2020
* Added ability to set Disco Ball and VU Meter on indefinitely.
* Mode 13 is the new Always on Disco Ball
* Mode 12 is the timed Disco Ball
* Mode 92 is VU Meter (always on) to match Logic commanding
* Mode 21 is VU Meter timed
* Restored the fast switch between USB Serial and Tx/Rx Pin Serial
*
* Version 0.96 - 5th April 2020
* Added address checking for T commands
* 0 is all
* 4 is Front PSI
* 5 is rear PSI as taken from Marc's Teeces command guide.
*
* Address field is interpreted as follows:
* 0 - global address, all displays that support the command are set
* 1 - TFLD (Top Front Logic Dislay)
* 2 - BFLD (Bottom Front Logic Display)
* 3 - RLD (Rear Logic Display)
* 4 - Front PSI
* 5 - Rear PSI
* 6 - Front Holo (not implemented here)
* 7 - Rear Holo (not implemented here)
* 8 - Top Holo (not implemented here)
*
* Version 0.9.5 - 5th April 2020
* Star Wars scrolling text sequence added
* Minor bug fixes
*
* Version 0.94 - 4th April 2020
* Comments cleanup and clarification
* More timing tweaks
* Work around added for serial difficulties with non Sparkfun Pro Micro
*
*
* Version 0.93 - 1st April 2020 (Happy April Fools Day!)
* Code cleanup, and code size reduction
* Timing tweaks from Malcolm for various sequences.
* Updated JawaLite To support A, D and P (P used to change always on mode)
* T1 (Swipe) is now the default sequence, as MarcDuino sends 0T1 on startup.
* Added the ability to set the default pattern in the config.h
* Note that MarcDuino will send 0T1, so whatever is in Mode 1 will be the starting pattern.
* After that point when a sequence completes, it will restore the "defaultPattern"
* as defined in config.h
* EEPROM Support added to store various global settings:
* alwaysOn config
* Internal or External POT use
* Internal brightness setting if using Internal Brightness value (1P1 was sent)
* Fixed a bug in the VU Meter Sequence.
*
* Version 0.8 - 31st March 2020
* Added Lightsaber Battle animation
* Added Pulse for rear logic dsiplay on T9
* Updated JawaLite Commanding on Serial to be 0Txx format
* Added the ability to change the serial port by defining USB_SERIAL.
* Uncomment #define USB_SERIAL for serial comunications using Tx and Rx (removed again)
* Set the default behavior for unrecognised commands to just keep running the swipe pattern.
* Configuration data moved to config.h rather than being scattered.
*
* Version 0.7 - 30th March 2020
* Non-Delay version of code.
* Allows sequences to be interrupted at ay time.
* Waiting for sequence completion is no longer required
* Set the default brightness in setup from the Brightness POT
*
* Version 0.6 - 29th March 2020
* Base versions of most sequences implented
* Support for Front/Rear color selection using Jumper implemented
* Brightness Pot implemented
*
*
* ***************************
* ********* WARNING *********
* ***************************
*
* This PSI CAN DRAW MORE POWER THAN YOUR COMPUTER'S USB PORT CAN SUPPLY!!
*
* When using the USB connection on the Pro Micro to power the PSI (during programming
* for instance) be sure to have the brightness POT turned nearly all the way COUNTERCLOCKWISE.
* Having the POT turned up too far when plugged into USB can damage the Pro Micro and/or your
* computer's USB port!!!! If you are using the internal brightness control and are connected
* to USB, KEEP THIS VALUE LOW, not higher than 20. The Pro Micro can also be removed from the
* PSI and programmed separately.
*
*
*
* ///////////////////////// COMMANDS AND COMMAND STRUCTURE /////////////////////////
*
*
* Supported JAWALite Commands via Serial or i2c:
*
* Serial:
*
* Command T - Trigger a numbered Mode. Txx where xx is the pattern number below. When using the R2 Touch app, commands
* should be in the form @0Tx\r or @0Txx\r. Please see below for address information for the T command.
*
* The Optional time parameter can be sent by adding |yy to the T command. Commands should be in the form
* @0Tx|y. y is a value in seconds.
*
* Command A - Go to Main mode of operation which is Standard Swipe Pattern.
* @0A from R2 Touch
*
* Command D - Go to Default mode which is the Standard Swipe Pattern.
* @0D from R2 Touch
*
* Command xPy - Sets various board parameters.
* If x is 0, Set the alwaysOn behavior of the panel
* The default mode for the panel is to display command sequences for
* a given time, then revert to the default pattern (swipe).
* By sending the xPy command, this can be changed.
* y is either 0 or 1 (default or always on mode)
* 0P0 - Default mode, where default pattern (swipe) is restored after the sequence plays
* 0P1 - The sequence continues to play until a new comand is received.
*
* If x is 1, Set the POT mode
* The default is to read the external POT value for setting brightness
* y is either 0 or 1 (Pot or internal setting)
* 1P0 - Default mode, uses the external POT to set the LED brightness
* 1P1 - Use the internal brightness, which is set using command 2Py below
*
* If x is 2, Set the internal brightness value, overriding the POT.
* The default setting is that brightness is 20.
* y is a value between 0 (off) and 255 (max brightness) Values over 200
* will be limited to 200 to preserve the life of the LEDs. This value
* is saved to the EPROM and will persist after power down.
* for example: 2Py or 2Pyy or 2Pyyy
*
* If x is 3, Set the internal brighness value, overriding the POT, but do not save to EEPROM.
* 3P0 will restore the brightness to it's previous value. If that was POT control, the POT setting
* will be used, it if was internal brightness, then the previous global internal brightness witll be used.
* 3Pyyy will set the brightness in the range 1 to 200. Values over 200 will be limited to 200 to preserve
* the life of the LEDs.
*
* @xPy from R2 Touch (You don't need the '0' before the x when using the P command.
*
* ***************************
* ******** WARNING ********
* ***************************
*
* This PSI CAN DRAW MORE POWER THAN YOUR computer's USB PORT CAN SUPPLY!! When using the USB connection
* on the Pro Micro to power the PSI (during programming for instance) be sure to have the brightness
* POT turned nearly all the way COUNTERCLOCKWISE. Having the POT turned up too far when plugged into
* USB can damage the Pro Micro and/or your computer's USB port!!!! If you are using the internal brightness
* control and are connected to USB, KEEP THIS VALUE LOW, not higher than 20. The Pro Micro can also be removed
* from the PSI and programmed separately.
*
* i2c:
*
* When sending i2c command the Panel Address is defined on the config.h tab to be 22. The command type and value are needed.
* To trigger a pattern, send an address (0 for all, 4 for front, 5 for rear) then the character 'T' and the Mode value corresponding
* to the pattern list below to trigger the corresponding sequence. Sequences must be terminated with a carriage return (\r).
*
* Using i2c with the R2 Touch app, commands must be sent in hex. For example, &220T6\r would be spelled &22,x33,x54,x36,x0D\r
*
* Commands:
*
* Address modifiers for "T" commands. The digit preceeding the T is the address:
*
* 0 is all
* 4 is Front PSI
* 5 is Rear PSI as taken from Marc's Teeces command guide.
*
* Address field is interpreted as follows:
* 0 - global address, all displays that support the command are set
* 1 - TFLD (Top Front Logic Dislay)
* 2 - BFLD (Bottom Front Logic Display)
* 3 - RLD (Rear Logic Display)
* 4 - Front PSI
* 5 - Rear PSI
* 6 - Front Holo (not implemented here)
* 7 - Rear Holo (not implemented here)
* 8 - Top Holo (not implemented here)
*
* Command T Modes
* Sensitivity to flashing lights can be as slow as 3x/second.
* e.g. Flash, Alarm, Scream
* You must be cautious.
*
* Mode 0 - Turn Panel off (This will also turn stop the Teeces if they share the serial connection and the "0" address is used)
* Mode 1 - Default (Swipe) The default mode can be changed on the config.h tab
* Mode 2 - Flash (fast flash) (4 seconds) Use caution around those sensitive to flashing lights.
* Mode 3 - Alarm (slow flash) (4 seconds)
* Mode 4 - Short Circuit (10 seconds)
* Mode 5 - Scream (4 seconds)
* Mode 6 - Leia Message (34 seconds)
* Mode 7 - I Heart U (10 seconds)
* Mode 8 - Quarter Panel Sweep (7 seconds)
* Mode 9 - Flashing Red Heart (Front PSI), Pulse Monitor (Rear PSI)
* Mode 10 - Star Wars - Title Scroll (15 seconds)
* Mode 11 - Imperial March (47 seconds)
* Mode 12 - Disco Ball (4 seconds)
* Mode 13 - Disco Ball - Runs Indefinitely
* Mode 14 - Rebel Symbol (5 seconds)
* Mode 15 - Knight Rider (20 seconds)
* Mode 16 - Test Sequence (White on Indefinitely)
* Mode 17 - Red on Indefinitely
* Mode 18 - Green on Indefinitely
* Mode 19 - LightSaber Battle
* Mode 20 - Star Wars Intro (scrolling yellow "text" getting smaller and dimmer)
* Mode 21 - VU Meter (4 seconds)
* Mode 92 - VU Meter - Runs Indefinitely (Spectrum on Teeces)
*
* Most users shouldn't need to change anything below this line. Please see the config.h tab
* for user adjustable settings.
*/
// Include the various libraries that we need.
#include <FastLED.h>
#include <EEPROM.h>
#include "matrices.h"
#include "config.h"
#if USE_I2C
#include "Wire.h"
#endif
// Setup the LED Matrix
CRGB leds[NUM_LEDS];
// Brightness control
bool internalBrightness = false;
bool useTempInternalBrightness = false;
uint8_t globalBrightnessValue = 20; // Set to a default of 20. This is overridden in the P command or read from EEPROM.
uint8_t tempGlobalBrightnessValue = 20; // Used in the 3Pyyy command to temporarily use internal brightness for script use.
uint8_t previousglobalPOTaverage = 0;
uint8_t tempglobalPOTaverage = 10;
uint8_t globalPOTaverage = 10; // Used to store the POT average for brightness setting with the POT.
// Command loop processing times
unsigned long previousMillis = 0;
unsigned long interval = 25;
//counters and state stuff
unsigned long doNext;
unsigned long globalTimeout;
// Global animation stuff is defined here.
int updateLed = 0;
int ledPatternState;
bool firstTime;
bool patternRunning = false;
uint8_t globalPatternLoops;
// Timing values received from command are stored here.
bool timingReceived = false;
unsigned long commandTiming = 0;
// Used for the VU display to store global state ...
int level[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
//Serial Stuff
int lastPSIeventCode = defaultPattern;
bool firstTimeCode = true;
// handle to the Serial object
Stream* serialPort;
// Swipe Default pattern stuff
enum state {
Primary,
PrimaryToSecondary,
Secondary,
SecondaryToPrimary
};
// Global animation state for the Swipe Default sequence is defined here
state ledState = Primary;
uint8_t visibleSecondaryColumns = 0;
unsigned long nextEvent = 0;
unsigned long swipeDelay = 0;
unsigned long lastLedUpdate = 0;
CRGB overlayColors[COLUMNS];
// Setup
void setup() {
// Setup LED defaults
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
pinMode(JUMP_FRONT_REAR, INPUT_PULLUP);
//Sets the default brightness, this reads from the POT and sets the value
FastLED.setBrightness(brightness());
#if USE_I2C
// Setup I2C
Wire.begin(I2CAdress); // Start I2C Bus as Master I2C Address
Wire.onReceive(receiveEvent); // register event so when we receive something we jump to receiveEvent();
#endif
// Setup the Serial for debug and command input
// initialize suart used to communicate with the JEDI Display at 2400 or 9600 bauds
// This is set in config.h
uint16_t baudrate;
#ifdef _9600BAUDSJEDI_
baudrate=9600;
#else
baudrate=2400;
#endif
// Setup for Official Pro Micro. The offical PRO can switch like this.
#ifdef USB_SERIAL
// If we want to debug on the USB, then we use Serial
Serial.begin(baudrate);
serialPort=&Serial;
#else
Serial1.begin(baudrate);
serialPort=&Serial1;
#endif
// READ the default settings from the EEPROM
byte value;
// Set the Always on Behavior.
value = EEPROM.read(alwaysOnAddress);
if (value == 0) {
alwaysOn = false;
DEBUG_PRINT_LN("Panel Behaviour set to default, run sequence then default");
}
if (value == 1) {
alwaysOn = true;
DEBUG_PRINT_LN("Panel Behaviour set to always on. Send new command to change sequence.");
}
value = EEPROM.read(externalPOTAddress);
if (value == 0) {
internalBrightness = false;
DEBUG_PRINT_LN("Using External POT for brightness control");
}
if (value == 1) {
internalBrightness = true;
DEBUG_PRINT_LN("Using Internal value for brightness control");
}
value = EEPROM.read(internalBrightnessAddress);
globalBrightnessValue = value;
DEBUG_PRINT("Global LED Brightness set to :"); DEBUG_PRINT_LN(globalBrightnessValue);
DEBUG_PRINT_LN("Ready");
}
// Main loop
void loop()
{
// Get current time.
unsigned long currentMillis = millis();
uint8_t delta;
if (currentMillis - previousMillis > interval)
{
//DEBUG_PRINT_LN("Main Loop Tick");
previousMillis = currentMillis;
if (patternRunning)
{
runPattern(lastPSIeventCode);
}
else
{
lastPSIeventCode = defaultPattern;
runPattern(lastPSIeventCode);
}
// Grab the POT Average value.
tempglobalPOTaverage = averagePOT();
delta = (tempglobalPOTaverage >= previousglobalPOTaverage) ? tempglobalPOTaverage - previousglobalPOTaverage : previousglobalPOTaverage - tempglobalPOTaverage;
// Allow you to debounce the POT :D
if (delta > POT_VARIANCE_LEVEL){
previousglobalPOTaverage = tempglobalPOTaverage;
globalPOTaverage = tempglobalPOTaverage;
}
}
}
//////////////////////////
// LED Helper Functions //
//////////////////////////
void allON(CRGB color, bool showLED, unsigned long runtime=0)
{
if (firstTime) {
DEBUG_PRINT_LN("Turn on all LEDs");
firstTime = false;
patternRunning = true;
if ((runtime != 0) && (!timingReceived)) set_global_timeout(runtime);
if (timingReceived) set_global_timeout(commandTiming);
}
fill_solid(leds, NUM_LEDS, color);
if (showLED) FastLED.show(brightness());
if ((runtime != 0) || (timingReceived)){
// Check for the global timeout to have expired.
globalTimerDonedoRestoreDefault();
}
}
void allOFF(bool showLED, unsigned long runtime=0)
{
if (firstTime) {
DEBUG_PRINT_LN("All Off");
firstTime = false;
patternRunning = true;
DEBUG_PRINT_LN(runtime);
if ((runtime != 0) && (!timingReceived)) set_global_timeout(runtime);
if (timingReceived) set_global_timeout(commandTiming);
}
//DEBUG_PRINT_LN("LED All Off");
FastLED.clear();
if (showLED) FastLED.show();
if ((runtime != 0) || (timingReceived)) {
// Check for the global timeout to have expired.
globalTimerDonedoRestoreDefault();
}
}
void fill_column(uint8_t column, CRGB color, uint8_t scale_brightness=0) {
for (int i = 0; i < LEDS_PER_COLUMN; i++) {
int8_t ledIndex = ledMatrix[column][i];
if (ledIndex != -1) {
leds[ledIndex] = color;
if (scale_brightness != 0) leds[ledIndex] %= scale_brightness;
}
}
}
// Fills half a column. 0 for top half, 1 for bottom half.
void fill_half_column(uint8_t column, uint8_t half, CRGB color) {
uint8_t start;
uint8_t end_col;
if (!half) {
start = 0;
end_col = LEDS_PER_COLUMN / 2;
}
else
{
start = LEDS_PER_COLUMN / 2;
end_col = LEDS_PER_COLUMN;
}
for (int i = start; i < end_col; i++) {
int8_t ledIndex = ledMatrix[column][i];
if (ledIndex != -1) leds[ledIndex] = color;
}
}
void fill_row(uint8_t row, CRGB color, uint8_t scale_brightness=0) {
for (int i = 0; i < COLUMNS; i++) {
int8_t ledIndex = ledMatrix[i][row];
if (ledIndex != -1) {
leds[ledIndex] = color;
if (scale_brightness != 0) leds[ledIndex] %= scale_brightness;
}
}
}
// Display a solid line across each row in ascending or decending order, based on the scanDirection.
// Scan Direction:
// 0: Scan down from the top row
// 1: Scan up from the bottom row.
void scanRow(unsigned long time_delay, int start_row, CRGB color, bool scanDirection)
{
if (firstTime) {
if (scanDirection == 0) ledPatternState = start_row;
// Down
if (scanDirection == 1) ledPatternState = (LEDS_PER_COLUMN - 1) - start_row;
firstTime = false;
patternRunning = true;
}
updateLed = 0;
if (checkDelay()) {
switch (ledPatternState) {
case 0: {
allOFF(true);
fill_row(0, color);
updateLed = 1;
break;
}
case 1: {
allOFF(true);
fill_row(1, color);
updateLed = 1;
break;
}
case 2: {
allOFF(true);
fill_row(2, color);
updateLed = 1;
break;
}
case 3: {
allOFF(true);
fill_row(3, color);
updateLed = 1;
break;
}
case 4: {
allOFF(true);
fill_row(4, color);
updateLed = 1;
break;
}
case 5: {
allOFF(true);
fill_row(5, color);
updateLed = 1;
break;
}
default: {
// Do nothing.
break;
}
}
// Increment the state.
if (scanDirection == 0) ledPatternState++;
if (scanDirection == 1) ledPatternState--;
if (ledPatternState < 0)
{
ledPatternState = (LEDS_PER_COLUMN - 1);
globalPatternLoops--;
}
else if (ledPatternState > (LEDS_PER_COLUMN - 1))
{
ledPatternState = 0;
globalPatternLoops--;
}
}
if (updateLed) {
FastLED.show(brightness());
set_delay(time_delay);
}
}
// Scans down the rows starting at the first specified row from the bottom
void scanRowDownUp(unsigned long time_delay, int start_row, CRGB color, bool scanDirection)
{
if (firstTime) {
if (scanDirection == 0) ledPatternState = start_row;
if (scanDirection == 1) ledPatternState = (LEDS_PER_COLUMN - 1) - start_row;
firstTime = false;
patternRunning = true;
}
updateLed = 0;
if (checkDelay()) {
switch (ledPatternState) {
case 0: {
allOFF(true);
fill_row(0, color);
updateLed = 1;
break;
}
case 1: {
allOFF(true);
fill_row(1, color);
updateLed = 1;
break;
}
case 2: {
allOFF(true);
fill_row(2, color);
updateLed = 1;
break;
}
case 3: {
allOFF(true);
fill_row(3, color);
updateLed = 1;
break;
}
case 4: {
allOFF(true);
fill_row(4, color);
updateLed = 1;
break;
}
case 5: {
allOFF(true);
fill_row(5, color);
updateLed = 1;
break;
}
case 6: {
allOFF(true);
fill_row(4, color);
updateLed = 1;
break;
}
case 7: {
allOFF(true);
fill_row(3, color);
updateLed = 1;
break;
}
case 8: {
allOFF(true);
fill_row(2, color);
updateLed = 1;
break;
}
case 9: {
allOFF(true);
fill_row(1, color);
updateLed = 1;
break;
}
default: {
// Do nothing.
break;
}
}
// Increment the state.
if (scanDirection == 0) ledPatternState++;
if (scanDirection == 1) ledPatternState--;
if (ledPatternState < 0)
{
ledPatternState = 9;
globalPatternLoops--;
}
else if (ledPatternState > 9)
{
ledPatternState = 0;
globalPatternLoops--;
}
}
if (updateLed) {
FastLED.show(brightness());
set_delay(time_delay);
}
}
// Display a solid line across each row in ascending or decending order, based on the scanDirection.
// Scan Direction of 0 will scan right to left across the columns starting at the first specified row from the right.
// Scan Direction of 1 will scan left to right across the columns starting at the first specified row from the left.
void scanCol(unsigned long time_delay, int start_col, CRGB color, bool scanDirection)
{
if (firstTime) {
if (scanDirection == 0) ledPatternState = start_col;
// Down
if (scanDirection == 1) ledPatternState = (COLUMNS - 1) - start_col;
firstTime = false;
patternRunning = true;
}
updateLed = 0;
if (checkDelay()) {
switch (ledPatternState) {
case 0: {
allOFF(true);
fill_column(0, color);
updateLed = 1;
break;
}
case 1: {
allOFF(true);
fill_column(1, color);
updateLed = 1;
break;
}
case 2: {
allOFF(true);
fill_column(2, color);
updateLed = 1;
break;
}
case 3: {
allOFF(true);
fill_column(3, color);
updateLed = 1;
break;
}
case 4: {
allOFF(true);
fill_column(4, color);
updateLed = 1;
break;
}
case 5: {
allOFF(true);
fill_column(5, color);
updateLed = 1;
break;
}
case 6: {
allOFF(true);
fill_column(6, color);
updateLed = 1;
break;
}
case 7: {
allOFF(true);
fill_column(7, color);
updateLed = 1;
break;
}
case 8: {
allOFF(true);
fill_column(8, color);
updateLed = 1;
break;
}
case 9: {
allOFF(true);
fill_column(9, color);
updateLed = 1;
break;
}
default: {
// Do nothing.
break;
}
}
// Increment the state.
if (scanDirection == 0) ledPatternState++;
if (scanDirection == 1) ledPatternState--;
if (ledPatternState < 0)
{
ledPatternState = (COLUMNS - 1);
globalPatternLoops--;
}
else if (ledPatternState > (COLUMNS - 1))
{
ledPatternState = 0;
globalPatternLoops--;
}
}
if (updateLed) {
FastLED.show(brightness());
set_delay(time_delay);
}
}
// Sweeps Left/Right or Right/Left across the columns.
// Scan Direction of 0 will scan right to left across the columns starting at the first specified row from the right.
// Scan Direction of 1 will scan left to right across the columns starting at the first specified row from the left.
void scanColLeftRight(unsigned long time_delay, int start_row, CRGB color, bool scanDirection)
{
if (firstTime) {
if (scanDirection == 0) ledPatternState = start_row;
if (scanDirection == 1) ledPatternState = 9 - start_row;
firstTime = false;
patternRunning = true;
}
updateLed = 0;
if (checkDelay()) {
switch (ledPatternState) {
case 0: {
allOFF(true);
fill_column(0, color);
updateLed = 1;
break;
}
case 1: {
allOFF(true);
fill_column(1, color);
updateLed = 1;
break;
}
case 2: {
allOFF(true);
fill_column(2, color);
updateLed = 1;
break;
}
case 3: {
allOFF(true);
fill_column(3, color);
updateLed = 1;
break;
}
case 4: {
allOFF(true);
fill_column(4, color);
updateLed = 1;
break;
}
case 5: {
allOFF(true);
fill_column(5, color);
updateLed = 1;
break;
}
case 6: {
allOFF(true);
fill_column(6, color);
updateLed = 1;
break;
}
case 7: {
allOFF(true);
fill_column(7, color);
updateLed = 1;
break;
}
case 8: {
allOFF(true);
fill_column(8, color);
updateLed = 1;
break;
}
case 9: {
allOFF(true);
fill_column(9, color);
updateLed = 1;
break;
}
case 10: {
allOFF(true);
fill_column(8, color);
updateLed = 1;
break;
}
case 11: {
allOFF(true);
fill_column(7, color);
updateLed = 1;
break;
}
case 12: {
allOFF(true);
fill_column(6, color);
updateLed = 1;
break;
}
case 13: {
allOFF(true);
fill_column(5, color);
updateLed = 1;
break;
}
case 14: {
allOFF(true);
fill_column(4, color);
updateLed = 1;
break;
}
case 15: {
allOFF(true);
fill_column(3, color);
updateLed = 1;
break;
}
case 16: {
allOFF(true);
fill_column(2, color);
updateLed = 1;
break;
}
case 17: {
allOFF(true);
fill_column(1, color);
updateLed = 1;
break;
}
default: {
// Do nothing.
break;
}
}
// Increment the state.
if (scanDirection == 0) ledPatternState++;
if (scanDirection == 1) ledPatternState--;
if (ledPatternState < 0)
{
ledPatternState = 17;
globalPatternLoops--;
}
else if (ledPatternState > 17)
{
ledPatternState = 0;
globalPatternLoops--;
}
}
if (updateLed) {
FastLED.show(brightness());
set_delay(time_delay);
}
}
// Display a matrix using the byte array. Colours are defined so that
// if the matrix has a 1, we use fgcolor, and 0 is bgcolor.
// Optionally colors 2,3,4,5,6,7,8 (allowing a total of nine colours to be used in a pattern.
void displayMatrixColor(const byte* matrix, CRGB fgcolor, CRGB bgcolor, bool displayMe, unsigned long runtime,
CRGB color2=0x000000, CRGB color3=0x000000, CRGB color4=0x000000, CRGB color5=0x000000,
CRGB color6=0x000000, CRGB color7=0x000000, CRGB color8=0x000000)
{
// global LED ID counter ...
int ledNum = 0;
byte ledOn;
if (firstTime) {
firstTime = false;
patternRunning = true;
// AllOff will set the timing, so we don't want to re-set it if timing was received for single display patterns!
// Special case where we don't want to use the global timeout!
if (timingReceived) {
set_global_timeout(commandTiming);
runtime = 0;
}
if (runtime != 0) set_global_timeout(runtime);