19#include "math_macros.h"
24#include "screenmap.json.h"
37constexpr int lengths[] = {
52CRGB leds0[lengths[BlackStrip]] = {};
53CRGB leds1[lengths[GreenStrip]] = {};
54CRGB leds2[lengths[RedStrip]] = {};
55CRGB leds3[lengths[BlueStrip]] = {};
56CRGB *leds[] = {leds0, leds1, leds2, leds3};
59byte ledColors[40][14][3];
64Slider decay(
"decay", .97f, .8, 1.0, .01);
68#define numberOfRipples 30
69Ripple ripples[numberOfRipples] = {
80float highestIrReading;
83#define heartbeatLockout \
85#define heartbeatDelta 300
88#define lowTemperature 33.0
89#define highTemperature 37.0
90float lastKnownTemperature =
91 (lowTemperature + highTemperature) /
99#define gyroThreshold \
101float gyroX, gyroY, gyroZ;
105#define randomPulsesEnabled true
106#define cubePulsesEnabled true
107Checkbox starburstPulsesEnabled(
"Starburst Pulses",
true);
108Checkbox simulatedBiometricsEnabled(
"Simulated Biometrics",
true);
110#define autoPulseTimeout \
113#define randomPulseTime 2000
114unsigned long lastRandomPulse;
115byte lastAutoPulseNode = 255;
117byte numberOfAutoPulseTypes =
118 randomPulsesEnabled + cubePulsesEnabled + int(starburstPulsesEnabled);
119byte currentAutoPulseType = 255;
120#define autoPulseChangeTime 30000
121unsigned long lastAutoPulseChange;
123#define simulatedHeartbeatBaseTime \
125#define simulatedHeartbeatVariance \
127#define simulatedEdaBaseTime 1000
128#define simulatedEdaVariance 10000
129unsigned long nextSimulatedHeartbeat;
130unsigned long nextSimulatedEda;
133bool isNodeOnBorder(
byte node) {
134 for (
int i = 0; i < numberOfBorderNodes; i++) {
135 if (node == borderNodes[i]) {
142Checkbox allWhite(
"All White",
false);
144Button simulatedHeartbeat(
"Simulated Heartbeat");
145Button triggerStarburst(
"Trigger Starburst");
146Button triggerRainbowCube(
"Rainbow Cube");
147Button triggerBorderWave(
"Border Wave");
148Button triggerSpiral(
"Spiral Wave");
149bool wasHeartbeatClicked =
false;
150bool wasStarburstClicked =
false;
151bool wasRainbowCubeClicked =
false;
152bool wasBorderWaveClicked =
false;
153bool wasSpiralClicked =
false;
156 Serial.begin(115200);
158 Serial.println(
"*** LET'S GOOOOO ***");
160 Serial.println(
"JSON SCREENMAP");
161 Serial.println(JSON_SCREEN_MAP);
164 ScreenMap::ParseJson(JSON_SCREEN_MAP, &segmentMaps);
166 printf(
"Parsed %d segment maps\n",
int(segmentMaps.size()));
167 for (
auto kv : segmentMaps) {
168 Serial.print(kv.first);
170 Serial.println(kv.second.getLength());
177 ok = segmentMaps.get(
"red_segment", &red) && ok;
178 ok = segmentMaps.get(
"back_segment", &black) && ok;
179 ok = segmentMaps.get(
"green_segment", &green) && ok;
180 ok = segmentMaps.get(
"blue_segment", &blue) && ok;
182 Serial.println(
"Failed to get all segment maps");
187 CRGB* red_leds = leds[RedStrip];
188 CRGB* black_leds = leds[BlackStrip];
189 CRGB* green_leds = leds[GreenStrip];
190 CRGB* blue_leds = leds[BlueStrip];
203 unsigned long benchmark = millis();
209 for (
int strip = 0; strip < 40; strip++) {
210 for (
int led = 0; led < 14; led++) {
211 for (
int i = 0; i < 3; i++) {
212 ledColors[strip][led][i] *= decay.value();
217 for (
int i = 0; i < numberOfRipples; i++) {
218 ripples[i].advance(ledColors);
221 for (
int segment = 0; segment < 40; segment++) {
222 for (
int fromBottom = 0; fromBottom < 14; fromBottom++) {
223 int strip = ledAssignments[segment][0];
224 int led = round(fmap(fromBottom, 0, 13, ledAssignments[segment][2],
225 ledAssignments[segment][1]));
226 leds[strip][led] =
CRGB(ledColors[segment][fromBottom][0],
227 ledColors[segment][fromBottom][1],
228 ledColors[segment][fromBottom][2]);
234 for (
int i = 0; i < 4; i++) {
235 for (
int j = 0; j < lengths[i]; j++) {
245 wasHeartbeatClicked = bool(simulatedHeartbeat);
246 wasStarburstClicked = bool(triggerStarburst);
247 wasRainbowCubeClicked = bool(triggerRainbowCube);
248 wasBorderWaveClicked = bool(triggerBorderWave);
249 wasSpiralClicked = bool(triggerSpiral);
251 if (wasSpiralClicked) {
253 unsigned int baseColor = random(0xFFFF);
254 byte centerNode = 15;
257 for (
int i = 0; i < 6; i++) {
258 if (nodeConnections[centerNode][i] >= 0) {
259 for (
int j = 0; j < numberOfRipples; j++) {
260 if (ripples[j].state == dead) {
263 Adafruit_DotStar_ColorHSV(
264 baseColor + (0xFFFF / 6) * i, 255, 255),
267 i % 2 ? alwaysTurnsLeft : alwaysTurnsRight);
273 lastHeartbeat = millis();
276 if (wasBorderWaveClicked) {
278 unsigned int baseColor = random(0xFFFF);
281 for (
int i = 0; i < numberOfBorderNodes; i++) {
282 byte node = borderNodes[i];
284 for (
int dir = 0; dir < 6; dir++) {
285 if (nodeConnections[node][dir] >= 0 &&
286 !isNodeOnBorder(nodeConnections[node][dir])) {
287 for (
int j = 0; j < numberOfRipples; j++) {
288 if (ripples[j].state == dead) {
291 Adafruit_DotStar_ColorHSV(
292 baseColor + (0xFFFF / numberOfBorderNodes) * i,
302 lastHeartbeat = millis();
305 if (wasRainbowCubeClicked) {
307 int node = cubeNodes[random(numberOfCubeNodes)];
308 unsigned int baseColor = random(0xFFFF);
309 byte behavior = random(2) ? alwaysTurnsLeft : alwaysTurnsRight;
311 for (
int i = 0; i < 6; i++) {
312 if (nodeConnections[node][i] >= 0) {
313 for (
int j = 0; j < numberOfRipples; j++) {
314 if (ripples[j].state == dead) {
317 Adafruit_DotStar_ColorHSV(
318 baseColor + (0xFFFF / 6) * i, 255, 255),
325 lastHeartbeat = millis();
328 if (wasStarburstClicked) {
330 unsigned int baseColor = random(0xFFFF);
331 byte behavior = random(2) ? alwaysTurnsLeft : alwaysTurnsRight;
333 for (
int i = 0; i < 6; i++) {
334 for (
int j = 0; j < numberOfRipples; j++) {
335 if (ripples[j].state == dead) {
338 Adafruit_DotStar_ColorHSV(
339 baseColor + (0xFFFF / 6) * i, 255, 255),
340 .65, 1500, behavior);
345 lastHeartbeat = millis();
348 if (wasHeartbeatClicked) {
350 for (
int i = 0; i < 6; i++) {
351 for (
int j = 0; j < numberOfRipples; j++) {
352 if (ripples[j].state == dead) {
353 ripples[j].start(15, i, 0xEE1111,
354 float(random(100)) / 100.0 * .1 + .4, 1000, 0);
359 lastHeartbeat = millis();
362 if (millis() - lastHeartbeat >= autoPulseTimeout) {
364 if (numberOfAutoPulseTypes &&
365 millis() - lastRandomPulse >= randomPulseTime) {
366 unsigned int baseColor = random(0xFFFF);
368 if (currentAutoPulseType == 255 ||
369 (numberOfAutoPulseTypes > 1 &&
370 millis() - lastAutoPulseChange >= autoPulseChangeTime)) {
371 byte possiblePulse = 255;
373 possiblePulse = random(3);
375 if (possiblePulse == currentAutoPulseType)
378 switch (possiblePulse) {
380 if (!randomPulsesEnabled)
385 if (!cubePulsesEnabled)
390 if (!starburstPulsesEnabled)
398 currentAutoPulseType = possiblePulse;
399 lastAutoPulseChange = millis();
404 switch (currentAutoPulseType) {
407 bool foundStartingNode =
false;
408 while (!foundStartingNode) {
410 foundStartingNode =
true;
411 for (
int i = 0; i < numberOfBorderNodes; i++) {
414 if (node == borderNodes[i])
415 foundStartingNode =
false;
418 if (node == lastAutoPulseNode)
419 foundStartingNode =
false;
422 lastAutoPulseNode = node;
424 for (
int i = 0; i < 6; i++) {
425 if (nodeConnections[node][i] >= 0) {
426 for (
int j = 0; j < numberOfRipples; j++) {
427 if (ripples[j].state == dead) {
433 Adafruit_DotStar_ColorHSV(baseColor, 255,
435 float(random(100)) / 100.0 * .2 + .5, 3000,
447 int node = cubeNodes[random(numberOfCubeNodes)];
449 while (node == lastAutoPulseNode)
450 node = cubeNodes[random(numberOfCubeNodes)];
452 lastAutoPulseNode = node;
454 byte behavior = random(2) ? alwaysTurnsLeft : alwaysTurnsRight;
456 for (
int i = 0; i < 6; i++) {
457 if (nodeConnections[node][i] >= 0) {
458 for (
int j = 0; j < numberOfRipples; j++) {
459 if (ripples[j].state == dead) {
465 Adafruit_DotStar_ColorHSV(baseColor, 255,
478 byte behavior = random(2) ? alwaysTurnsLeft : alwaysTurnsRight;
480 lastAutoPulseNode = starburstNode;
482 for (
int i = 0; i < 6; i++) {
483 for (
int j = 0; j < numberOfRipples; j++) {
484 if (ripples[j].state == dead) {
487 Adafruit_DotStar_ColorHSV(
488 baseColor + (0xFFFF / 6) * i, 255, 255),
489 .65, 1500, behavior);
501 lastRandomPulse = millis();
504 if (simulatedBiometricsEnabled) {
506 if (millis() >= nextSimulatedHeartbeat) {
507 for (
int i = 0; i < 6; i++) {
508 for (
int j = 0; j < numberOfRipples; j++) {
509 if (ripples[j].state == dead) {
512 float(random(100)) / 100.0 * .1 + .4, 1000, 0);
519 nextSimulatedHeartbeat = millis() + simulatedHeartbeatBaseTime +
520 random(simulatedHeartbeatVariance);
524 if (millis() >= nextSimulatedEda) {
525 for (
int i = 0; i < 10; i++) {
526 for (
int j = 0; j < numberOfRipples; j++) {
527 if (ripples[j].state == dead) {
529 borderNodes[random(numberOfBorderNodes)];
530 byte direction = 255;
532 while (direction == 255) {
533 direction = random(6);
534 if (nodeConnections[targetNode][direction] < 0)
539 targetNode, direction, 0x1111EE,
540 float(random(100)) / 100.0 * .5 + 2, 300, 2);
547 nextSimulatedEda = millis() + simulatedEdaBaseTime +
548 random(simulatedEdaVariance);
CFastLED FastLED
Global LED strip management instance.
central include file for FastLED, defines the CFastLED class/object
void show(uint8_t scale)
Update all our controllers with the current led colors, using the passed in brightness.
static CLEDController & addLeds(CLEDController *pLed, struct CRGB *data, int nLedsOrOffset, int nLedsIfOffset=0)
Add a CLEDController instance to the world.
Representation of an RGB pixel (Red, Green, Blue)