/* Single Function DotStar LED Strip Driver - see http://www.technoblogy.com/show?3SO4 David Johnson-Davies - www.technoblogy.com - 4th February 2022 CC BY 4.0 Licensed under a Creative Commons Attribution 4.0 International license: http://creativecommons.org/licenses/by/4.0/ */ #include // Constants const int LEDs = 72; // Adjust this for your LED strip const int Brightness = 1; // Global brightness 1 to 31 enum rgb_values { red, green, blue }; enum hsv_values { hue, sat, value }; const float pi = acos(0) * 2; // Utilities float fract (float x) { return x - int(x); } float clamp (float v, float lo, float hi) { return (vhi) ? hi : v; } void WriteLEDs (float *rgb) { for (int i=2; i>=0; i--) SPI.transfer(round(powf(2.0, rgb[i]*8)) - 1); } float *HSVtoRGB (float *hsv) { static float rgb[3]; const int xbits = 0b100100; const int cbits = 0b011000; float h = hsv[0]*6; float chroma = hsv[2] * hsv[1]; float x = chroma * (1 - abs(fmod(h, 2) - 1)); float m = hsv[2] - chroma; for (int i=0; i<3; i++) { int j = ((int)h + i*2) % 6; rgb[2-i] = m + (cbits>>j & 1) * chroma + (xbits>>j & 1) * x; } return rgb; } // RGB examples ********************************************** float *Cylon (float x, float t) { static float rgb[3]; float x2 = 0.375 * (1 - sin(2 * pi * t/4)); float value = (1 - cos(clamp(x-x2, 0, 0.25) * 8 * pi)) / 2; rgb[red] = value; rgb[green] = 0; rgb[blue] = 0; return rgb; } float *Gradient (float x, float t) { static float rgb[3]; rgb[red] = x; rgb[green] = 0; rgb[blue] = 0; return rgb; } float *Chameleon (float x, float t) { static float rgb[3]; rgb[red] = abs(2*fract(t/21) - 1); rgb[green] = abs(2*fract((7 + t)/21) - 1); rgb[blue] = abs(2*fract((14 + t)/21) - 1); return rgb; } float *TwinPeaks (float x, float t) { static float rgb[3]; float colour1 = (1 - cos(clamp(fract(x + t), 0, 0.5) * 4 * pi)) / 2; float colour2 = (1 - cos(clamp(fract(1 - x + t), 0, 0.5) * 4 * pi)) / 2; rgb[red] = colour1; rgb[green] = 0; rgb[blue] = colour2; return rgb; } float *Explosion (float x, float t) { static float rgb[3]; float tt = (fmod(t/100, 20.0) - 10.0); float xx = 2*x - 1.0; float f = xx * xx + tt * tt; rgb[red] = fract(f + 0.33); rgb[green] = fract(f); rgb[blue] = fract(f + 0.66); return rgb; } float *Scanner (float x, float t) { static float rgb[3]; int xx = x * (float)LEDs; int tt = (int)(t / 2.0 * (float)LEDs) % LEDs; rgb[red] = (xx == tt) ? 1 : 0; rgb[green] = 0; rgb[blue] = 0; return rgb; } float *Pendulums (float x, float t) { static float rgb[3]; int xx = x * (float)LEDs; float s = sin(2 * pi * (t / 4.0)); float c = cos(2 * pi * (t / 4.0)); float h = (float)LEDs/2; int t0 = (s + 1) * h; // Red int t1 = (c + 1) * h; // Green int t2 = (1 - s) * h; // Blue int t3 = (1 - c) * h; // Cyan rgb[red] = (xx == t0) ? 1 : 0; rgb[green] = (xx == t1 | xx == t3) ? 1 : 0; rgb[blue] = (xx == t2 | xx == t3) ? 1 : 0; return rgb; } float *Fireworks (float x, float t) { static float rgb[3]; float value1 = (1 - cos(clamp(x, 0, 0.5) * 4 * pi)) / 2; float value2 = (1 - cos(clamp(x-0.25, 0, 0.5) * 4 * pi)) / 2; float value3 = (1 - cos(clamp(x-0.5, 0, 0.5) * 4 * pi)) / 2; rgb[red] = (1 - fract(t/6))*value1; rgb[green] = (1 - fract((t+4)/6))*value2; rgb[blue] = (1 - fract((t+2)/6))*value3; return rgb; } // HSV examples ********************************************** float *Spectrum (float x, float t) { static float hsv[3]; hsv[hue] = x; hsv[sat] = 1; hsv[value] = 1; return HSVtoRGB(hsv); } float *MoodLight (float x, float t) { static float hsv[3]; hsv[hue] = fract(1 - x/6 + t/100); hsv[sat] = 1; hsv[value] = 1; return HSVtoRGB(hsv); } float *Gradient2 (float x, float t) { static float hsv[3]; hsv[hue] = 0; hsv[sat] = 1; hsv[value] = x; return HSVtoRGB(hsv); } float *Twinkle (float x, float t) { static float hsv[3]; int n = 1 + t * 10.0; int k = 30 + (int)(x * LEDs); hsv[hue] = fract(x * 10); hsv[sat] = 1; hsv[value] = (n % k == 0) ? 1 : 0; return HSVtoRGB(hsv); } // Main program ********************************************** void setup() { SPI.begin(); } void loop() { long start = millis(); for (;;) { float t = (float)(millis() - start) / 1000.0; for (int i=0; i<4; i++) SPI.transfer(0); // Start frame for (int i=0; i