aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Harrington <kb0iic@berzerkula.org>2022-03-17 21:55:29 -0500
committerWilliam Harrington <kb0iic@berzerkula.org>2022-03-17 21:55:29 -0500
commitb27dee0cca0456f6f57e751f0e6fa2486a67d552 (patch)
tree8b29ec7a1c0d5a7543d6296c5b3d34023bc6fdfe
initial commit
-rw-r--r--EveryLaserXCharXHsv/EveryLaserXCharXHsv.ino335
-rw-r--r--EveryLaserXCharXRgb/EveryLaserXCharXRgb.ino179
-rw-r--r--EveryLaserXSerialChar/EveryLaserXSerialChar.ino815
-rw-r--r--EveryLaserXTest/EveryLaserXTest.ino144
-rw-r--r--Readme.md5
5 files changed, 1478 insertions, 0 deletions
diff --git a/EveryLaserXCharXHsv/EveryLaserXCharXHsv.ino b/EveryLaserXCharXHsv/EveryLaserXCharXHsv.ino
new file mode 100644
index 0000000..6eba618
--- /dev/null
+++ b/EveryLaserXCharXHsv/EveryLaserXCharXHsv.ino
@@ -0,0 +1,335 @@
+/*
+ * Connect LED (string) to pin D4 (PC6) of the Arduino Nano Every.
+ *
+ * Author: Clemens at Elektor
+ * Date: 30/12/2021
+ *
+ * Board: Arduino Nano Every
+ * Arduino IDE 1.8.15
+ */
+#include <Nano_Every_WS2812B.h>
+CI_WS2812B LEDs;
+
+// Number of LaserX displays daisychained
+const int NUMDISP = 4;
+
+// LaserX displays have 14 SK8216's in series with with one WS2812B at the end
+const int LEDSPERDISP = 15;
+
+// Multiply number of LEDs per display with number of displays
+const int NUMLEDS = NUMDISP * LEDSPERDISP;
+
+const byte ARRAY_SIZE = 95;
+
+ci_ws2812b_rgb_t rgb[NUMLEDS];
+
+uint8_t red, green, blue = 0;
+
+// Hue
+int angle = 0;
+
+// Brightness
+int brightness = 0;
+
+const uint8_t lights[360]={
+ 0, 0, 0, 0, 0, 1, 1, 2,
+ 2, 3, 4, 5, 6, 7, 8, 9,
+ 11, 12, 13, 15, 17, 18, 20, 22,
+ 24, 26, 28, 30, 32, 35, 37, 39,
+ 42, 44, 47, 49, 52, 55, 58, 60,
+ 63, 66, 69, 72, 75, 78, 81, 85,
+ 88, 91, 94, 97, 101, 104, 107, 111,
+114, 117, 121, 124, 127, 131, 134, 137,
+141, 144, 147, 150, 154, 157, 160, 163,
+167, 170, 173, 176, 179, 182, 185, 188,
+191, 194, 197, 200, 202, 205, 208, 210,
+213, 215, 217, 220, 222, 224, 226, 229,
+231, 232, 234, 236, 238, 239, 241, 242,
+244, 245, 246, 248, 249, 250, 251, 251,
+252, 253, 253, 254, 254, 255, 255, 255,
+255, 255, 255, 255, 254, 254, 253, 253,
+252, 251, 251, 250, 249, 248, 246, 245,
+244, 242, 241, 239, 238, 236, 234, 232,
+231, 229, 226, 224, 222, 220, 217, 215,
+213, 210, 208, 205, 202, 200, 197, 194,
+191, 188, 185, 182, 179, 176, 173, 170,
+167, 163, 160, 157, 154, 150, 147, 144,
+141, 137, 134, 131, 127, 124, 121, 117,
+114, 111, 107, 104, 101, 97, 94, 91,
+ 88, 85, 81, 78, 75, 72, 69, 66,
+ 63, 60, 58, 55, 52, 49, 47, 44,
+ 42, 39, 37, 35, 32, 30, 28, 26,
+ 24, 22, 20, 18, 17, 15, 13, 12,
+ 11, 9, 8, 7, 6, 5, 4, 3,
+ 2, 2, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+
+const uint8_t HSVlights[61] =
+{0, 4, 8, 13, 17, 21, 25, 30, 34, 38, 42, 47, 51, 55, 59, 64, 68, 72, 76,
+81, 85, 89, 93, 98, 102, 106, 110, 115, 119, 123, 127, 132, 136, 140, 144,
+149, 153, 157, 161, 166, 170, 174, 178, 183, 187, 191, 195, 200, 204, 208,
+212, 217, 221, 225, 229, 234, 238, 242, 246, 251, 255};
+
+const uint8_t HSVpower[121] =
+{0, 2, 4, 6, 8, 11, 13, 15, 17, 19, 21, 23, 25, 28, 30, 32, 34, 36, 38, 40,
+42, 45, 47, 49, 51, 53, 55, 57, 59, 62, 64, 66, 68, 70, 72, 74, 76, 79, 81,
+83, 85, 87, 89, 91, 93, 96, 98, 100, 102, 104, 106, 108, 110, 113, 115, 117,
+119, 121, 123, 125, 127, 130, 132, 134, 136, 138, 140, 142, 144, 147, 149,
+151, 153, 155, 157, 159, 161, 164, 166, 168, 170, 172, 174, 176, 178, 181,
+183, 185, 187, 189, 191, 193, 195, 198, 200, 202, 204, 206, 208, 210, 212,
+215, 217, 219, 221, 223, 225, 227, 229, 232, 234, 236, 238, 240, 242, 244,
+246, 249, 251, 253, 255};
+
+// the real HSV rainbow
+void trueHSV(int angle) {
+ if (angle<60) {
+ red = 255;
+ green = HSVlights[angle];
+ blue = 0;
+ } else if (angle<120) {
+ red = HSVlights[120-angle];
+ green = 255;
+ blue = 0;
+ } else if (angle<180) {
+ red = 0;
+ green = 255;
+ blue = HSVlights[angle-120];
+ } else if (angle<240) {
+ red = 0;
+ green = HSVlights[240-angle];
+ blue = 255;
+ } else if (angle<300) {
+ red = HSVlights[angle-240];
+ green = 0;
+ blue = 255;
+ } else {
+ red = 255;
+ green = 0;
+ blue = HSVlights[360-angle];
+ }
+}
+
+// the 'power-conscious' HSV rainbow
+void powerHSV(int angle)
+{
+ if (angle<120) {
+ red = HSVpower[120-angle];
+ green = HSVpower[angle];
+ blue = 0;
+ } else if (angle<240) {
+ red = 0;
+ green = HSVpower[240-angle];
+ blue = HSVpower[angle-120];
+ } else {
+ red = HSVpower[angle-240];
+ green = 0;
+ blue = HSVpower[360-angle];
+ }
+}
+
+// sine wave rainbow
+uint8_t sineRGB(int angle)
+{
+ red = lights[(angle+120)%360];
+ green = lights[angle];
+ blue = lights[(angle+240)%360];
+}
+
+// Available characters a 7 Segment display can show
+// TODO Move to Progmem
+uint16_t character_pixels[ ARRAY_SIZE ] {
+ /*' '*/ 0b0000000000000000,
+ /*'!'*/ 0b0000000000011000,
+ /*'"'*/ 0b0001000000000010,
+ /*'#'*/ 0b0011000011001110,
+ /*'$'*/ 0b0011000011101101,
+ /*'%'*/ 0b0000010100100100,
+ /*'&'*/ 0b0000101101011001,
+ /*'''*/ 0b0000000100000000,
+ /*'('*/ 0b0001001000000000,
+ /*')'*/ 0b0000011000000000,
+ /*'*'*/ 0b0011111100000000,
+ /*'+'*/ 0b0011000011000000,
+ /*','*/ 0b0000010000000000,
+ /*'-'*/ 0b0000000011000000,
+ /*'.'*/ 0b0100000000000000,
+ /*'/'*/ 0b0000010100000000,
+ /*'0'*/ 0b0000000000111111,
+ /*'1'*/ 0b0000000100000110,
+ /*'2'*/ 0b0000000011011011,
+ /*'3'*/ 0b0000000011001111,
+ /*'4'*/ 0b0000000011100110,
+ /*'5'*/ 0b0000000011101101,
+ /*'6'*/ 0b0000000011111100,
+ /*'7'*/ 0b0010000100000001,
+ /*'8'*/ 0b0000000011111111,
+ /*'9'*/ 0b0000000011100111,
+ /*':'*/ 0b0000000000000000,
+ /*';'*/ 0b0000000000000000,
+ /*'<'*/ 0b0000100100000000,
+ /*'='*/ 0b0000000011001000,
+ /*'>'*/ 0b0000011000000000,
+ /*'?'*/ 0b0010000010000011,
+ /*'@'*/ 0b0000000000000000,
+ /*'A'*/ 0b0000000011110111,
+ /*'B'*/ 0b0011000010001111,
+ /*'C'*/ 0b0000000000111001,
+ /*'D'*/ 0b0011000000001111,
+ /*'E'*/ 0b0000000011111001,
+ /*'F'*/ 0b0000000001110001,
+ /*'G'*/ 0b0000000010111101,
+ /*'H'*/ 0b0000000011110110,
+ /*'I'*/ 0b0011000000001001,
+ /*'J'*/ 0b0000000000011110,
+ /*'K'*/ 0b0000100101110000,
+ /*'L'*/ 0b0000000000111000,
+ /*'M'*/ 0b0000001100110110,
+ /*'N'*/ 0b0000101000110110,
+ /*'O'*/ 0b0000000000111111,
+ /*'P'*/ 0b0000000011110011,
+ /*'Q'*/ 0b0000100000111111,
+ /*'R'*/ 0b0000100101110001,
+ /*'S'*/ 0b0000001010001101,
+ /*'T'*/ 0b0011000000000001,
+ /*'U'*/ 0b0000000000111110,
+ /*'V'*/ 0b0000010100110000,
+ /*'W'*/ 0b0000110000110110,
+ /*'X'*/ 0b0000111100000000,
+ /*'Y'*/ 0b0010001100000000,
+ /*'Z'*/ 0b0000010100001001,
+ /*'['*/ 0b0000000000111001,
+ /*'\'*/ 0b0000101000000000,
+ /*']'*/ 0b0000000000001111,
+ /*'^'*/ 0b0000000000000000,
+ /*'_'*/ 0b0000000000001000,
+ /*'`'*/ 0b0000001000000000,
+ /*'a'*/ 0b0000000011110111,
+ /*'b'*/ 0b0011000010001111,
+ /*'c'*/ 0b0000000000111001,
+ /*'d'*/ 0b0011000000001111,
+ /*'e'*/ 0b0000000011111001,
+ /*'f'*/ 0b0000000001110001,
+ /*'g'*/ 0b0000000010111101,
+ /*'h'*/ 0b0000000011110110,
+ /*'i'*/ 0b0011000000001001,
+ /*'j'*/ 0b0000000000011110,
+ /*'k'*/ 0b0000100101110000,
+ /*'l'*/ 0b0000000000111000,
+ /*'m'*/ 0b0000001100110110,
+ /*'n'*/ 0b0000101000110110,
+ /*'o'*/ 0b0000000000111111,
+ /*'p'*/ 0b0000000011110011,
+ /*'q'*/ 0b0000100000111111,
+ /*'r'*/ 0b0000100101110001,
+ /*'s'*/ 0b0000001010001101,
+ /*'t'*/ 0b0011000000000001,
+ /*'y'*/ 0b0000000000111110,
+ /*'v'*/ 0b0000010100110000,
+ /*'w'*/ 0b0000110000110110,
+ /*'x'*/ 0b0000111100000000,
+ /*'y'*/ 0b0010001100000000,
+ /*'z'*/ 0b0000010100001001,
+ /*'{'*/ 0b0000011001001001,
+ /*'|'*/ 0b0011000000000000,
+ /*'}'*/ 0b0000100110001001,
+ /*'~'*/ 0b0000000000000000,
+};
+
+uint16_t findCharacterX( byte c )
+{
+ for ( int i = 0; i < sizeof(character_pixels); i++ )
+ {
+ if ( character_pixels[i] == c ) {
+ return character_pixels[i];
+ }
+ }
+
+ return character_pixels[0];
+}
+
+void setup(void)
+{
+ Serial.begin(115200);
+ LEDs.begin();
+}
+
+void loop() {
+
+ for (int charX = 0; charX < 37; charX++) {
+
+ for (int disp = 0; disp < NUMDISP; disp++) {
+
+ int charIndex = charX + disp;
+
+ if (charIndex >= 37) {
+ charIndex = 0;
+ }
+
+ uint16_t dispChar = character_pixels[charIndex];
+
+ for (uint8_t led = 0; led < LEDSPERDISP; led++) {
+
+ int ledIndex = (LEDSPERDISP * disp) + led;
+
+ if (dispChar & (1 << led)) {
+ //bit is 1
+ //set color
+
+ // true rainbow
+ //trueHSV(angle);
+
+ // power conscious HSV rainbow
+ powerHSV(angle);
+
+ // sinewave RGB
+ //sineRGB(angle);
+ rgb[ledIndex].r = red;
+ rgb[ledIndex].g = green;
+ rgb[ledIndex].b = blue;
+ } else {
+ //bit is 0
+ //set no color
+ rgb[ledIndex].r = 0;
+ rgb[ledIndex].g = 0;
+ rgb[ledIndex].b = 0;
+ }
+
+// Serial.print("Angle: ");
+// Serial.print(angle);
+// Serial.print(" Red: ");
+// Serial.print(red);
+// Serial.print(" Green: ");
+// Serial.print(green);
+// Serial.print(" Blue: ");
+// Serial.println(blue);
+
+ }
+
+ }
+
+ if (angle < 360) {
+ angle++;
+ } else {
+ angle = 0;
+ }
+
+ LEDs.write_string(NUMLEDS, rgb);
+
+ delay(500);
+
+ }
+}
diff --git a/EveryLaserXCharXRgb/EveryLaserXCharXRgb.ino b/EveryLaserXCharXRgb/EveryLaserXCharXRgb.ino
new file mode 100644
index 0000000..7b8f3af
--- /dev/null
+++ b/EveryLaserXCharXRgb/EveryLaserXCharXRgb.ino
@@ -0,0 +1,179 @@
+/*
+ * Connect LED (string) to pin D4 (PC6) of the Arduino Nano Every.
+ *
+ * Author: Clemens at Elektor
+ * Date: 30/12/2021
+ *
+ * Board: Arduino Nano Every
+ * Arduino IDE 1.8.15
+ */
+#include <Nano_Every_WS2812B.h>
+CI_WS2812B LEDs;
+
+// Number of LaserX displays daisychained
+const uint8_t NUMDISP = 4;
+
+// LaserX displays have 14 SK8216's in series with with one WS2812B at the end
+const uint8_t LEDSPERDISP = 15;
+
+// Multiply number of LEDs per display with number of displays
+const uint8_t NUMLEDS = NUMDISP * LEDSPERDISP;
+
+const byte ARRAY_SIZE = 58;
+
+ci_ws2812b_rgb_t rgb[NUMLEDS];
+
+float counter = 0;
+float pi = 3.14159;
+int redSin, greenSin, blueSin = 0;
+uint8_t red, green, blue = 0;
+uint8_t maxLevel = 48;
+
+// Available characters a 7 Segment display can show
+// TODO Move to Progmem
+uint16_t character_pixels[ ARRAY_SIZE ] {
+ /*' '*/ 0b0000000000000000,
+ /*'0'*/ 0b0000000000111111,
+ /*'1'*/ 0b0000000100000110,
+ /*'2'*/ 0b0000000011011011,
+ /*'3'*/ 0b0000000011001111,
+ /*'4'*/ 0b0000000011100110,
+ /*'5'*/ 0b0000000011101101,
+ /*'6'*/ 0b0000000011111100,
+ /*'7'*/ 0b0010000100000001,
+ /*'8'*/ 0b0000000011111111,
+ /*'9'*/ 0b0000000011100111,
+ /*'a'*/ 0b0000000011110111,
+ /*'b'*/ 0b0011000010001111,
+ /*'c'*/ 0b0000000000111001,
+ /*'d'*/ 0b0011000000001111,
+ /*'e'*/ 0b0000000011111001,
+ /*'f'*/ 0b0000000001110001,
+ /*'g'*/ 0b0000000010111101,
+ /*'h'*/ 0b0000000011110110,
+ /*'i'*/ 0b0011000000001001,
+ /*'j'*/ 0b0000000000011110,
+ /*'k'*/ 0b0000100101110000,
+ /*'l'*/ 0b0000000000111000,
+ /*'m'*/ 0b0000001100110110,
+ /*'n'*/ 0b0000101000110110,
+ /*'o'*/ 0b0000000000111111,
+ /*'p'*/ 0b0000000011110011,
+ /*'q'*/ 0b0000100000111111,
+ /*'r'*/ 0b0000100101110001,
+ /*'s'*/ 0b0000001010001101,
+ /*'t'*/ 0b0011000000000001,
+ /*'u'*/ 0b0000000000111110,
+ /*'v'*/ 0b0000010100110000,
+ /*'w'*/ 0b0000110000110110,
+ /*'x'*/ 0b0000111100000000,
+ /*'y'*/ 0b0010001100000000,
+ /*'z'*/ 0b0000010100001001,
+ /*'*'*/ 0b0011111100000000,
+ /*'+'*/ 0b0011000011000000,
+ /*'-'*/ 0b0000000011000000,
+ /*'/'*/ 0b0000010100000000,
+ /*'<'*/ 0b0000100100000000,
+ /*'>'*/ 0b0000011000000000,
+ /*'|'*/ 0b0011000000000000,
+ /*'$'*/ 0b0011000011101101,
+ /*'?'*/ 0b0010000010000011,
+
+ /*'!'*/ 0b0000000000011000,
+ /*'#'*/ 0b0011000011001110,
+ /*'%'*/ 0b0000010100100100,
+ /*'&'*/ 0b0000101101011001,
+ /*'`'*/ 0b0000001000000000,
+ /*'['*/ 0b0000000000111001,
+ /*']'*/ 0b0000000000001111,
+ /*','*/ 0b0000010000000000,
+
+ /*'='*/ 0b0000000011001000,
+ /*'_'*/ 0b0000000000001000,
+ /*'{'*/ 0b0000011001001001,
+ /*'}'*/ 0b0000100110001001,
+};
+
+uint16_t findCharacterX( byte c )
+{
+ for ( int i = 0; i < sizeof(character_pixels); i++ )
+ {
+ if ( character_pixels[i] == c ) {
+ return character_pixels[i];
+ }
+ }
+
+ return character_pixels[0];
+}
+
+uint8_t getRGB(char color) {
+
+ redSin = sin(counter / 100) * 1000;
+ greenSin = sin(counter / 100 + pi * 2 / 3) * 1000;
+ blueSin = sin(counter / 100 + pi * 4 / 3) * 1000;
+
+ red = map(redSin, -1000, 1000, 0, maxLevel);
+ green = map(greenSin, -1000, 1000, 0, maxLevel);
+ blue = map(blueSin, -1000, 1000, 0, maxLevel);
+
+ switch (color) {
+ case 'r': return red; break;
+ case 'g': return green; break;
+ case 'b': return blue; break;
+ default : return 0;
+ }
+}
+
+void setup(void)
+{
+ //Serial.begin(115200);
+ LEDs.begin();
+ delay(10);
+}
+
+void loop() {
+
+ for (uint8_t charX = 0; charX < 37; charX++) {
+
+ for (uint8_t disp = 0; disp < NUMDISP; disp++) {
+
+ uint8_t charIndex = charX + disp;
+
+ if (charIndex >= 37) {
+ charIndex = 0;
+ }
+
+ uint16_t dispChar = character_pixels[charIndex];
+
+
+
+ for (uint8_t led = 0; led < LEDSPERDISP; led++) {
+
+ uint8_t ledIndex = (LEDSPERDISP * disp) + led;
+
+ if (dispChar & (1 << led)) {
+ //bit is 1
+ //set color
+ rgb[ledIndex].r = getRGB('r');
+ rgb[ledIndex].g = getRGB('g');
+ rgb[ledIndex].b = getRGB('b');
+ } else {
+ //bit is 0
+ //set no color
+ rgb[ledIndex].r = 0;
+ rgb[ledIndex].g = 0;
+ rgb[ledIndex].b = 0;
+ }
+
+ }
+
+ counter++;
+
+ }
+
+ LEDs.write_string(NUMLEDS, rgb);
+
+ delay(500);
+
+ }
+}
diff --git a/EveryLaserXSerialChar/EveryLaserXSerialChar.ino b/EveryLaserXSerialChar/EveryLaserXSerialChar.ino
new file mode 100644
index 0000000..3769381
--- /dev/null
+++ b/EveryLaserXSerialChar/EveryLaserXSerialChar.ino
@@ -0,0 +1,815 @@
+/*
+ * Connect LED (string) to pin D4 (PC6) of the Arduino Nano Every.
+ *
+ * Author: William Harrington
+ * Date: someday in the future
+ *
+ * Board: Arduino Nano Every
+ * Arduino IDE 1.8.19
+ */
+
+#include <avr/pgmspace.h>
+
+// https://github.com/ClemensAtElektor/Nano_Every_WS2812B
+#include <Nano_Every_WS2812B.h>
+
+typedef struct {
+ char id;
+ uint16_t pixels;
+} CharacterX;
+
+#define ELEMENTS(x) (sizeof(x) / sizeof(x[0]))
+
+CI_WS2812B LEDs;
+
+// Number of LaserX displays daisychained
+const int NUMDISP PROGMEM = 4;
+
+// LaserX displays have 14 SK8216's in series with with one WS2812B at the end
+const int LEDSPERDISP PROGMEM = 15;
+
+// Multiply number of LEDs per display with number of displays
+const int NUMLEDS PROGMEM = NUMDISP * LEDSPERDISP;
+
+ci_ws2812b_rgb_t rgb[NUMLEDS];
+
+uint8_t red = 0, green = 0, blue = 0;
+
+// For HSV
+float saturation = 0.5, value = 0.5;
+
+// colorSpace selector - default to True HSV
+// 0 - TrueHSV, 1 - PowerHSV, 2 - Varaible sat and val HSV, 3 - Sine RGB
+uint8_t colorSpace = 0;
+
+// color type 0 - fade, 1 - single
+uint8_t colorType = 0;
+
+// TIMER CLICKS
+const uint16_t TIMER_CLICKS PROGMEM = 4500; // 1mS periodic interrupt
+
+// Fade Delay(ms)
+uint16_t fadeDelay = 167; // 167ms fade rate at 16MHz/2 with TIMER_CLICKS interrupts
+
+// Hue
+int hue = 0;
+
+// Brightness (future use)
+int brightness = 0;
+
+// Default laserStr is empty
+String laserStr = "";
+
+// scroll type selector - default to no scroll
+// 0 - no scroll, 1 - scroll right, 2 - scroll left
+uint8_t scrollType = 0;
+
+// Scroll delay(ms)
+uint16_t scrollDelay = 1000; // 1000ms scroll rate at 16MHz/2 with TIMER_CLICKS interrupts
+
+// timer counters
+uint16_t scrollCounter = 0;
+uint16_t fadeCounter = 0;
+
+// counter for rgb sine wave with gamma fix
+float sineCounter = 0.0;
+float pi = 3.14159;
+
+const uint8_t lights[360] PROGMEM = {
+ 0, 0, 0, 0, 0, 1, 1, 2,
+ 2, 3, 4, 5, 6, 7, 8, 9,
+ 11, 12, 13, 15, 17, 18, 20, 22,
+ 24, 26, 28, 30, 32, 35, 37, 39,
+ 42, 44, 47, 49, 52, 55, 58, 60,
+ 63, 66, 69, 72, 75, 78, 81, 85,
+ 88, 91, 94, 97, 101, 104, 107, 111,
+114, 117, 121, 124, 127, 131, 134, 137,
+141, 144, 147, 150, 154, 157, 160, 163,
+167, 170, 173, 176, 179, 182, 185, 188,
+191, 194, 197, 200, 202, 205, 208, 210,
+213, 215, 217, 220, 222, 224, 226, 229,
+231, 232, 234, 236, 238, 239, 241, 242,
+244, 245, 246, 248, 249, 250, 251, 251,
+252, 253, 253, 254, 254, 255, 255, 255,
+255, 255, 255, 255, 254, 254, 253, 253,
+252, 251, 251, 250, 249, 248, 246, 245,
+244, 242, 241, 239, 238, 236, 234, 232,
+231, 229, 226, 224, 222, 220, 217, 215,
+213, 210, 208, 205, 202, 200, 197, 194,
+191, 188, 185, 182, 179, 176, 173, 170,
+167, 163, 160, 157, 154, 150, 147, 144,
+141, 137, 134, 131, 127, 124, 121, 117,
+114, 111, 107, 104, 101, 97, 94, 91,
+ 88, 85, 81, 78, 75, 72, 69, 66,
+ 63, 60, 58, 55, 52, 49, 47, 44,
+ 42, 39, 37, 35, 32, 30, 28, 26,
+ 24, 22, 20, 18, 17, 15, 13, 12,
+ 11, 9, 8, 7, 6, 5, 4, 3,
+ 2, 2, 1, 1, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0};
+
+// Gamma fix for linear input values
+const uint8_t gamma[] PROGMEM = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
+ 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
+ 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
+ 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
+ 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
+ 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
+ 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
+ 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
+ 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
+ 90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
+ 115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
+ 144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
+ 177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
+ 215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 };
+
+const uint8_t HSVlights[61] PROGMEM = {
+ 0, 4, 8, 13, 17, 21, 25, 30, 34, 38, 42, 47, 51, 55, 59, 64, 68, 72, 76,
+81, 85, 89, 93, 98, 102, 106, 110, 115, 119, 123, 127, 132, 136, 140, 144,
+149, 153, 157, 161, 166, 170, 174, 178, 183, 187, 191, 195, 200, 204, 208,
+212, 217, 221, 225, 229, 234, 238, 242, 246, 251, 255};
+
+const uint8_t HSVpower[121] PROGMEM = {
+ 0, 2, 4, 6, 8, 11, 13, 15, 17, 19, 21, 23, 25, 28, 30, 32, 34, 36, 38, 40,
+42, 45, 47, 49, 51, 53, 55, 57, 59, 62, 64, 66, 68, 70, 72, 74, 76, 79, 81,
+83, 85, 87, 89, 91, 93, 96, 98, 100, 102, 104, 106, 108, 110, 113, 115, 117,
+119, 121, 123, 125, 127, 130, 132, 134, 136, 138, 140, 142, 144, 147, 149,
+151, 153, 155, 157, 159, 161, 164, 166, 168, 170, 172, 174, 176, 178, 181,
+183, 185, 187, 189, 191, 193, 195, 198, 200, 202, 204, 206, 208, 210, 212,
+215, 217, 219, 221, 223, 225, 227, 229, 232, 234, 236, 238, 240, 242, 244,
+246, 249, 251, 253, 255};
+
+// Available characters a 7 Segment display can show
+// !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+const CharacterX character_pixels[] PROGMEM = {
+ ' ', 0b0000000000000000,
+ '!', 0b0000000000011000,
+ '"', 0b0001000000100000,
+ '#', 0b0011000011001110,
+ '$', 0b0011000011101101,
+ '%', 0b0000010100100100,
+ '&', 0b0000101101011001,
+ '\'', 0b0000000100000000,
+ '(', 0b0000100100000000,
+ ')', 0b0000011000000000,
+ '*', 0b0011111100000000,
+ '+', 0b0011000011000000,
+ ',', 0b0000010000000000,
+ '-', 0b0000000011000000,
+ '.', 0b0100000000000000,
+ '/', 0b0000010100000000,
+ '0', 0b0000000000111111,
+ '1', 0b0000000100000110,
+ '2', 0b0000000011011011,
+ '3', 0b0000000011001111,
+ '4', 0b0000000011100110,
+ '5', 0b0000000011101101,
+ '6', 0b0000000011111100,
+ '7', 0b0010000100000001,
+ '8', 0b0000000011111111,
+ '9', 0b0000000011100111,
+ ':', 0b0000000000000000,
+ ';', 0b0000000000000000,
+ '<', 0b0000100100000000,
+ '=', 0b0000000011001000,
+ '>', 0b0000011000000000,
+ '?', 0b0010000010000011,
+ '@', 0b0010000010111111,
+ 'A', 0b0000000011110111,
+ 'B', 0b0011000010001111,
+ 'C', 0b0000000000111001,
+ 'D', 0b0011000000001111,
+ 'E', 0b0000000011111001,
+ 'F', 0b0000000001110001,
+ 'G', 0b0000000010111101,
+ 'H', 0b0000000011110110,
+ 'I', 0b0011000000001001,
+ 'J', 0b0000000000011110,
+ 'K', 0b0000100101110000,
+ 'L', 0b0000000000111000,
+ 'M', 0b0000001100110110,
+ 'N', 0b0000101000110110,
+ 'O', 0b0000000000111111,
+ 'P', 0b0000000011110011,
+ 'Q', 0b0000100000111111,
+ 'R', 0b0000100101110001,
+ 'S', 0b0000001010001101,
+ 'T', 0b0011000000000001,
+ 'U', 0b0000000000111110,
+ 'V', 0b0000010100110000,
+ 'W', 0b0000110000110110,
+ 'X', 0b0000111100000000,
+ 'Y', 0b0010001100000000,
+ 'Z', 0b0000010100001001,
+ '[', 0b0000000000111001,
+ '\\', 0b0000101000000000,
+ ']', 0b0000000000001111,
+ '^', 0b0000001000100000,
+ '_', 0b0000000000001000,
+ '`', 0b0000001000000000,
+ 'a', 0b0000000011110111,
+ 'b', 0b0011000010001111,
+ 'c', 0b0000000000111001,
+ 'd', 0b0011000000001111,
+ 'e', 0b0000000011111001,
+ 'f', 0b0000000001110001,
+ 'g', 0b0000000010111101,
+ 'h', 0b0000000011110110,
+ 'i', 0b0011000000001001,
+ 'j', 0b0000000000011110,
+ 'k', 0b0000100101110000,
+ 'l', 0b0000000000111000,
+ 'm', 0b0000001100110110,
+ 'n', 0b0000101000110110,
+ 'o', 0b0000000000111111,
+ 'p', 0b0000000011110011,
+ 'q', 0b0000100000111111,
+ 'r', 0b0000100101110001,
+ 's', 0b0000001010001101,
+ 't', 0b0011000000000001,
+ 'u', 0b0000000000111110,
+ 'v', 0b0000010100110000,
+ 'w', 0b0000110000110110,
+ 'x', 0b0000111100000000,
+ 'y', 0b0010001100000000,
+ 'z', 0b0000010100001001,
+ '{', 0b0000011001001001,
+ '|', 0b0011000000000000,
+ '}', 0b0000100110001001,
+ '~', 0b1111111111111111,};
+
+// the real HSV rainbow
+void trueHSV(int hue) {
+ if (hue<60) {
+ red = 255;
+ green = pgm_read_byte(&HSVlights[hue]);
+ blue = 0;
+ } else if (hue<120) {
+ red = pgm_read_byte(&HSVlights[120-hue]);
+ green = 255;
+ blue = 0;
+ } else if (hue<180) {
+ red = 0;
+ green = 255;
+ blue = pgm_read_byte(&HSVlights[hue-120]);
+ } else if (hue<240) {
+ red = 0;
+ green = pgm_read_byte(&HSVlights[240-hue]);
+ blue = 255;
+ } else if (hue<300) {
+ red = pgm_read_byte(&HSVlights[hue-240]);
+ green = 0;
+ blue = 255;
+ } else {
+ red = 255;
+ green = 0;
+ blue = pgm_read_byte(&HSVlights[360-hue]);
+ }
+}
+
+// variable saturation and value HSV
+void svHSV(int hue, float saturation, float value) {
+ int i;
+ float f,p,q,t;
+ float h, s, v;
+
+ //expand the u8 hue in range 0->255 to 0->359* (there are problems at exactly 360)
+ h = hue;
+ s = saturation;
+ v = value;
+
+ if(s == 0) {
+ // Achromatic (grey)
+ red = round(v*255);
+ green = round(v*255);
+ blue = round(v*255);
+ return;
+ }
+
+ h /= 60; // sector 0 to 5
+ i = floor(h);
+ f = h - i; // factorial part of h
+ p = v * (1 - s);
+ q = v * (1 - s * f);
+ t = v * (1 - s * (1 - f));
+ switch(i) {
+ case 0:
+ red = round(255*v);
+ green = round(255*t);
+ blue = round(255*p);
+ break;
+ case 1:
+ red = round(255*q);
+ green = round(255*v);
+ blue = round(255*p);
+ break;
+ case 2:
+ red = round(255*p);
+ green = round(255*v);
+ blue = round(255*t);
+ break;
+ case 3:
+ red = round(255*p);
+ green = round(255*q);
+ blue = round(255*v);
+ break;
+ case 4:
+ red = round(255*t);
+ green = round(255*p);
+ blue = round(255*v);
+ break;
+ default: // case 5:
+ red = round(255*v);
+ green = round(255*p);
+ blue = round(255*q);
+ }
+}
+
+// the 'power-conscious' HSV rainbow
+void powerHSV(int hue) {
+ if (hue<120) {
+ red = pgm_read_byte(&HSVpower[120-hue]);
+ green = pgm_read_byte(&HSVpower[hue]);
+ blue = 0;
+ } else if (hue<240) {
+ red = 0;
+ green = pgm_read_byte(&HSVpower[240-hue]);
+ blue = pgm_read_byte(&HSVpower[hue-120]);
+ } else {
+ red = pgm_read_byte(&HSVpower[hue-240]);
+ green = 0;
+ blue = pgm_read_byte(&HSVpower[360-hue]);
+ }
+}
+
+void randomHSV() {
+ uint8_t color[3];
+ byte count, a0, a1, a2;
+ color[count] = random(256);
+ a0 = count + random(1) + 1;
+ color[a0 % 3] = random(256 - color[count]);
+ color[(a0 + 1) % 3] = 255 - color[a0 % 3] - color[count];
+ red = color[0];
+ green = color[1];
+ blue = color[2];
+ //count += random(15); // avoid repeating patterns
+ //count %= 3;
+}
+
+// sine wave rainbow
+void sineRGB(int hue) {
+ red = pgm_read_byte(&lights[(hue+120)%360]);
+ green = pgm_read_byte(&lights[hue]);
+ blue = pgm_read_byte(&lights[(hue+240)%360]);
+}
+
+// sine wave with gamma fix
+void sineRGB_gamma_fix() {
+ int redLevel = sin(sineCounter/100 + pi*2/3)*1000;
+ int greenLevel = sin(sineCounter/100 + pi*4/3)*1000;
+ int blueLevel = sin(sineCounter/100)*1000;
+ red = pgm_read_byte(&gamma[map(redLevel,-1000,1000,0,255)]);
+ green = pgm_read_byte(&gamma[map(blueLevel,-1000,1000,0,255)]);
+ blue = pgm_read_byte(&gamma[map(greenLevel,-1000,1000,0,255)]);
+}
+
+uint16_t findCharacterX( byte c ) {
+ CharacterX temp;
+
+ for ( uint8_t i = 0; i < ELEMENTS(character_pixels); i++ )
+ {
+ memcpy_P( &temp, &character_pixels[i], sizeof( CharacterX ));
+
+ if ( temp.id == c ) {
+ return temp.pixels;
+ }
+ }
+
+ return 0;
+}
+
+void nextColorSpace() {
+
+ colorSpace++;
+
+ if (colorSpace > 5) {
+ colorSpace = 0;
+ }
+
+ switch (colorSpace) {
+ case 0:
+ Serial.println("True HSV colorspace");
+ break;
+ case 1:
+ Serial.println("Power HSV colorspace");
+ break;
+ case 2:
+ Serial.println("Var SV HSV colorspace");
+ break;
+ case 3:
+ Serial.println("Random HSV colorspace");
+ break;
+ case 4:
+ Serial.println("Sine RGB colorspace");
+ break;
+ case 5:
+ Serial.println("Sine RGB gamma fix");
+ break;
+ default:
+ break;
+ }
+}
+
+void nextColorType() {
+ colorType++;
+
+ if (colorType > 1) {
+ colorType = 0;
+ }
+
+ switch (colorType) {
+ case 0:
+ Serial.println("Fade colors");
+ break;
+ case 1:
+ Serial.println("Single color");
+ break;
+ default:
+ break;
+ }
+}
+
+void setFadeDelay() {
+ String inString = "";
+ uint16_t newFadeDelay = 1000;
+
+ Serial.println("Enter fade delay and hit enter");
+
+ Serial.setTimeout(2500);
+ inString = Serial.parseInt();
+ Serial.setTimeout(1000);
+
+ newFadeDelay = inString.toInt();
+
+ Serial.print("New fade delay(ms): ");
+ Serial.println(newFadeDelay);
+
+ if (newFadeDelay > 0 && newFadeDelay < 10001) {
+ fadeDelay = newFadeDelay;
+ } else {
+ Serial.println("Fade delay out of range (1 - 10000)");
+ }
+}
+
+void setScrollDelay() {
+ String inString = "";
+ uint16_t newScrollDelay = 1000;
+
+ Serial.println("Enter fade delay and hit enter");
+
+ Serial.setTimeout(2500);
+ inString = Serial.parseInt();
+ Serial.setTimeout(1000);
+
+ newScrollDelay = inString.toInt();
+
+ Serial.print("New scroll delay(ms): ");
+ Serial.println(newScrollDelay);
+
+ if (newScrollDelay > 0 && newScrollDelay < 10001) {
+ scrollDelay = newScrollDelay;
+ } else {
+ Serial.println("Scroll delay out of range (1 - 10000)");
+ }
+}
+
+void setHue() {
+ if (colorType == 1) {
+ String inString = "";
+ int newHue = 0;
+
+ // Hue isn't sent if random colorspace is selected
+ // Set a color when single color type is selected
+ if (colorSpace == 3 && colorType == 1) {
+ Serial.println("Setting random color");
+ randomHSV();
+ return;
+ }
+
+ Serial.println("Enter hue/angle and hit enter");
+
+ Serial.setTimeout(2500);
+ inString = Serial.parseInt();
+ Serial.setTimeout(1000);
+
+ newHue = inString.toInt();
+ Serial.print("New hue/angle: ");
+ Serial.println(newHue);
+
+ if (newHue >= 0 && newHue < 360) {
+ hue = newHue;
+
+ // Shift hue/angle into rgb sine wave for gamma colorspace
+ sineCounter = map(hue,0,359,575,1257);
+ } else {
+ Serial.println("Hue/Angle out of range (0 - 359)");
+ }
+ }
+}
+
+void setColors() {
+
+ if (colorType == 0) {
+
+ sineCounter++;
+ //value = fabs(sin(sineCounter/100));
+ //saturation = fabs(sin(sineCounter/100 + (pi * 4/3)));
+
+ if (hue < 360) {
+ hue++;
+ } else {
+ hue = 0;
+ }
+ }
+
+ // true rainbow
+ if (colorSpace == 0)
+ trueHSV(hue);
+
+ // power conscious HSV rainbow
+ if (colorSpace == 1)
+ powerHSV(hue);
+
+ // variable saturation and value HSV
+ if (colorSpace == 2)
+ svHSV(hue, saturation, value);
+
+ // random HSV
+ if (colorSpace == 3 && colorType == 0)
+ randomHSV();
+
+ // sinewave RGB
+ if (colorSpace == 4)
+ sineRGB(hue);
+
+ // sinewave RGB with gamma fix
+ if (colorSpace == 5)
+ sineRGB_gamma_fix();
+}
+
+void setLaserStr() {
+ Serial.println("Enter string and press enter");
+
+ Serial.setTimeout(5000);
+ String laserStrnew = Serial.readStringUntil(13);
+ Serial.setTimeout(1000);
+
+ laserStr = laserStrnew;
+
+ // If str is less than number of displays, pad it with spaces
+ if (laserStr.length() < NUMDISP) {
+ for (uint8_t i = laserStr.length(); i < NUMDISP; i++) {
+ laserStr = laserStr + ' ';
+ }
+ }
+
+ Serial.println(laserStrnew);
+}
+
+void scrollText() {
+ switch (scrollType) {
+ case 1:
+ laserStr = shiftRight(laserStr);
+ break;
+ case 2:
+ laserStr = shiftLeft(laserStr);
+ break;
+ default:
+ break;
+ }
+}
+
+void nextScrollType() {
+ scrollType++;
+
+ if (scrollType > 2) {
+ scrollType = 0;
+ }
+
+ switch (scrollType) {
+ case 0:
+ Serial.println("Scroll OFF");
+ break;
+ case 1:
+ Serial.println("Scroll Right");
+ break;
+ case 2:
+ Serial.println("Scroll Left");
+ break;
+ default:
+ break;
+ }
+}
+
+void setSaturation() {
+ //if (colorType == 1) {
+ String inString = "";
+ float newSaturation = 0;
+
+ Serial.println("Enter saturation and hit enter");
+
+ Serial.setTimeout(2500);
+ inString = Serial.parseFloat();
+ Serial.setTimeout(1000);
+
+ newSaturation = inString.toFloat();
+ Serial.print("New saturation: ");
+ Serial.println(newSaturation);
+
+ if (newSaturation >= 0.0 && newSaturation <= 1.0) {
+ saturation = newSaturation;
+ } else {
+ Serial.println("Saturation out of range (0.0 - 1.0)");
+ }
+ //}
+}
+
+void setValue() {
+ String inString = "";
+ float newValue = 0.0;
+
+ Serial.println("Enter saturation and hit enter");
+
+ Serial.setTimeout(2500);
+ inString = Serial.parseFloat();
+ Serial.setTimeout(1000);
+
+ newValue = inString.toFloat();
+ Serial.print("New value: ");
+ Serial.println(newValue);
+
+ if (newValue >= 0.0 && newValue <= 1.0) {
+ value = newValue;
+ } else {
+ Serial.println("Value out of range (0.0 - 1.0)");
+ }
+}
+
+String shiftLeft(String str) {
+
+ uint8_t strlgth = str.length();
+ uint8_t first = str[0];
+
+ for (uint8_t i = 0; i < strlgth - 1; i++) {
+ str[i] = str[i + 1];
+ }
+
+ str[strlgth - 1] = first;
+ return str;
+}
+
+String shiftRight(String str) {
+ uint8_t strlgth = str.length();
+ uint8_t last = str[strlgth - 1];
+
+ for (uint8_t i = (strlgth - 1); i > 0; i--) {
+ str[i] = str[i - 1];
+ }
+
+ str[0] = last;
+ return str;
+}
+
+void updateCounters() {
+ scrollCounter++;
+ fadeCounter++;
+}
+
+ISR(TCB1_INT_vect) {
+ updateCounters();
+
+ if (fadeCounter >= fadeDelay) {
+ setColors();
+ fadeCounter = 0;
+ }
+
+ TCB1.INTFLAGS |= 0x00000001;
+}
+
+void writeStr(String charStr) {
+ for (int disp = 0; disp < NUMDISP; disp++) {
+ uint16_t c = findCharacterX(charStr[disp]);
+ for (uint8_t led = 0; led < LEDSPERDISP; led++) {
+ int ledIndex = (LEDSPERDISP * disp) + led;
+
+ if (c & (1 << led)) {
+ //bit is 1 and set color
+ rgb[ledIndex].r = red;
+ rgb[ledIndex].g = green;
+ rgb[ledIndex].b = blue;
+ } else {
+ //bit is 0 and set no color
+ rgb[ledIndex].r = 0;
+ rgb[ledIndex].g = 0;
+ rgb[ledIndex].b = 0;
+ }
+ }
+ }
+
+ LEDs.write_string(NUMLEDS, rgb);
+
+ if (scrollCounter >= scrollDelay) {
+ scrollText();
+ scrollCounter = 0;
+ }
+}
+
+void setup(void) {
+ Serial.begin(115200);
+ LEDs.begin();
+ Serial.println("c (colorspace) C (colortype)");
+ Serial.println("d (fade delay) D (scroll delay)");
+ Serial.println("h (hue/hue) s (scroll) t (text string)");
+ Serial.println("v (value) V (saturation)");
+
+ // Clear interrupt
+ cli();
+
+ // Configure TCB1
+ TCB1.CTRLA = 0; // Turn off channel for configuration
+ TCB1.CTRLA |= TCB_CLKSEL_CLKDIV2_gc; // Divide system clock by 2
+ TCB1.CTRLA |= TCB_ENABLE_bm; // Enable timer
+ TCB1.CTRLB = 0; // Periodic interrupt mode
+ TCB1.CCMP = TIMER_CLICKS; // Clocks per period
+ TCB1.INTCTRL = 0x00000001; // Enable interrupt
+ TCB1.CNT = 0;
+
+ // Set interrupt
+ sei();
+}
+
+
+void loop() {
+
+ //while (Serial.available() > 1 && Serial.read() == 27) {
+ while (Serial.available()) {
+ // Read incoming byte
+ uint8_t incomingByte = Serial.read();
+
+ switch (incomingByte) {
+ case 'c':
+ nextColorSpace();
+ break;
+ case 'C':
+ nextColorType();
+ break;
+ case 'd':
+ setFadeDelay();
+ break;
+ case 'D':
+ setScrollDelay();
+ break;
+ case 'h':
+ case 'H':
+ setHue();
+ break;
+ case 's':
+ case 'S':
+ nextScrollType();
+ break;
+ case 't':
+ case 'T':
+ setLaserStr();
+ break;
+ case 'v':
+ setValue();
+ break;
+ case 'V':
+ setSaturation();
+ break;
+ default:
+ break;
+ }
+
+ }
+
+ writeStr(laserStr);
+}
diff --git a/EveryLaserXTest/EveryLaserXTest.ino b/EveryLaserXTest/EveryLaserXTest.ino
new file mode 100644
index 0000000..e732230
--- /dev/null
+++ b/EveryLaserXTest/EveryLaserXTest.ino
@@ -0,0 +1,144 @@
+/*
+ * Connect LED (string) to pin D4 (PC6) of the Arduino Nano Every.
+ *
+ * Author: Clemens at Elektor
+ * Date: 30/12/2021
+ *
+ * Board: Arduino Nano Every
+ * Arduino IDE 1.8.15
+ */
+#include <Nano_Every_WS2812B.h>
+CI_WS2812B LEDs;
+//#define DEBUG 1
+
+float counter = 0;
+float pi = 3.14159;
+const uint8_t number_of_leds = 60; // The number of connected RGB LEDs.
+int red, green, blue = 0;
+
+ci_ws2812b_rgb_t rainbow[] =
+{
+ {255, 0, 0}, {255, 87, 0}, {205, 255, 0}, { 0, 255, 13},
+ {255, 105, 0}, {187, 255, 0}, { 0, 255, 30}, { 0, 255, 248},
+ {170, 255, 0}, { 0, 255, 48}, { 0, 243, 255}, { 0, 26, 255},
+ { 0, 255, 66}, { 0, 226, 255}, { 0, 8, 255}, { 0, 0, 255}
+};
+
+ci_ws2812b_rgb_t rainbow2[] =
+{
+ {100, 0, 0}, { 50, 25, 0}, { 25, 50, 0}, { 0, 100, 0},
+ { 50, 25, 0}, { 50, 25, 25}, { 25, 50, 25}, { 0, 50, 25},
+ { 25, 50, 0}, { 25, 50, 25}, { 25, 25, 50}, { 0, 25, 50},
+ { 0, 100, 0}, { 0, 50, 25}, { 0, 25, 50}, { 0, 0, 100},
+};
+
+ci_ws2812b_rgb_t rbox[] =
+{
+ {100,0,0}, {100,0,0}, {100,00}, {100,0,0},
+ {100,0,0}, {100,0,0}, {0,0,0}, {0,0,0},
+ {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
+ {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}
+};
+
+ci_ws2812b_rgb_t gbox[] =
+{
+ {0,100,0}, {0,100,0}, {0,100,0}, {0,100,0},
+ {0,100,0}, {0,100,0}, {0,0,0}, {0,0,0},
+ {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
+ {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}
+};
+
+ci_ws2812b_rgb_t bbox[] =
+{
+ {0,0,100}, {0,0,100}, {0,0,100}, {0,0,100},
+ {0,0,100}, {0,0,100}, {0,0,0}, {0,0,0},
+ {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0},
+ {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}
+};
+
+ci_ws2812b_rgb_t rgb[number_of_leds];
+
+void setup(void)
+{
+ LEDs.begin();
+ delay(100);
+
+ LEDs.write_string(number_of_leds, rainbow);
+ delay(1000);
+
+ LEDs.write_string(number_of_leds, rainbow2);
+ delay(1000);
+
+ LEDs.write_string(number_of_leds, rbox);
+ delay(1000);
+
+ LEDs.write_string(number_of_leds, gbox);
+ delay(1000);
+
+ LEDs.write_string(number_of_leds, bbox);
+ delay(1000);
+
+ for (uint8_t i = 0; i < number_of_leds; i++) {
+ LEDs.write(0, 0, 0);
+ }
+ delay(1000);
+
+ // From now on the CPU runs about 25% slower.
+ Serial.begin(115200); // About 25% higher to obtain 115200 baud.
+ Serial.println("Core-independent WS2812B driver");
+ Serial.println("This driver makes the CPU run at about 12 MHz.");
+ Serial.println("Adjust baud rates and delay times etc. accordingly.");
+ Serial.println("running...");
+}
+
+void loop(void)
+{
+
+ for (uint8_t i = 0; i < number_of_leds; i++) {
+ counter++;
+
+ #ifdef DEBUG
+ Serial.print("Counter: ");
+ Serial.print(counter);
+ #endif
+
+ red = sin(counter/100)*1000;
+ green = sin(counter/100 + pi*2/3)*1000;
+ blue = sin(counter/100 + pi*4/3)*1000;
+
+ #ifdef DEBUG
+ Serial.print(" SinR: ");
+ Serial.print(red);
+ Serial.print(" SinG: ");
+ Serial.print(green);
+ Serial.print(" SinB: ");
+ Serial.print(blue);
+ #endif
+
+ red = map(red,-1000,1000,0,50);
+ green = map(green,-1000,1000,0,50);
+ blue = map(blue,-1000,1000,0,50);
+
+ #ifdef DEBUG
+ Serial.print(" R: ");
+ Serial.print(red);
+ Serial.print(" G: ");
+ Serial.print(green);
+ Serial.print(" B: ");
+ Serial.println(blue);
+ #endif
+
+ rgb[i].r = red;
+ rgb[i].g = green;
+ rgb[i].b = blue;
+ }
+
+ LEDs.write_string(number_of_leds, rgb);
+
+ //for (uint8_t i = 0; i < number_of_leds; i++) {
+ // LEDs.write(rgb[i].r, rgb[i].g, rgb[i].b);
+ //}
+
+
+ delay(100); // About 100 ms on slowed-down CPU.
+}
diff --git a/Readme.md b/Readme.md
new file mode 100644
index 0000000..6f09c57
--- /dev/null
+++ b/Readme.md
@@ -0,0 +1,5 @@
+![LaserX](https://cdn.tindiemedia.com/images/resize/Suq2ovm21UW-9W1FzLR0cEvySIM=/p/full-fit-in/1168x876/i/96019/products/2018-12-03T03%3A58%3A49.888Z-Both_LitUp.jpg?1606306133
+
+# Laser Segment Display
+
+[A Laser Cut RGB LED 14 Segment Dislpay](https://www.tindie.com/products/seonr/laser-segment-display/)