+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/esp8266-fastled-webserver/data/js/app.js b/esp8266-fastled-webserver/data/js/app.js
index 13c5e8ee..02cba8be 100644
--- a/esp8266-fastled-webserver/data/js/app.js
+++ b/esp8266-fastled-webserver/data/js/app.js
@@ -28,6 +28,16 @@ var allData = {};
$(document).ready(function() {
$("#status").html("Connecting, please wait...");
+ // info gathers a lot more information ...
+ // just need product name for main page.
+ $.get(urlBase + "product", function (data) {
+ const name = data['productName'];
+ // Set overall page title
+ $(document).attr("title", name + " by EvilGenius Labs");
+ // Set text of element with id 'product'
+ $("#product").text(name);
+ });
+
$("#btnTop").click(function () {
$([document.documentElement, document.body]).animate(
{
@@ -460,6 +470,9 @@ function addSectionField(field) {
template.attr("id", "form-group-section-" + field.name);
template.attr("data-field-type", field.type);
+ var label = template.find(".section-header-text");
+ label.text(field.label);
+
$("#form").append(template);
}
diff --git a/esp8266-fastled-webserver/data/js/info.js b/esp8266-fastled-webserver/data/js/info.js
new file mode 100644
index 00000000..e901ab74
--- /dev/null
+++ b/esp8266-fastled-webserver/data/js/info.js
@@ -0,0 +1,81 @@
+// used when hosting the site on the ESP8266
+var address = location.hostname;
+var urlBase = "";
+
+// used when hosting the site somewhere other than the ESP8266 (handy for testing without waiting forever to upload to SPIFFS)
+// var address = "192.168.86.36";
+// var urlBase = "http://" + address + "/";
+
+const keyToName = {
+ millis: "Uptime",
+ vcc: "VCC",
+ wiFiChipId: "Wi-Fi Chip ID",
+ flashChipId: "Flash Chip ID",
+ flashChipSize: "Flash Chip Size",
+ flashChipRealSize: "Flash Chip Real Size",
+ sdkVersion: "SDK Version",
+ coreVersion: "Core Version",
+ bootVersion: "Boot Version",
+ cpuFreqMHz: "CPU Frequency",
+ freeHeap: "Free Heap Memory",
+ sketchSize: "Sketch Size",
+ freeSketchSpace: "Free Sketch Space",
+ resetReason: "Last Reset Reason",
+ isConnected: "Wi-Fi Connected",
+ wiFiSsidDefault: "Wi-Fi SSID (Default)",
+ wiFiSSID: "Wi-Fi SSID",
+ localIP: "Local IP Address",
+ gatewayIP: "Gateway IP Address",
+ subnetMask: "Subnet Mask",
+ dnsIP: "DNS IP Address",
+ hostname: "Hostname",
+ macAddress: "MAC Address",
+ autoConnect: "Auto Connect",
+ softAPSSID: "Soft AP SSID",
+ softAPIP: "Soft AP IP Address",
+ BSSID: "BSSID",
+ softAPmacAddress: "Soft AP MAC Address",
+};
+
+$(document).ready(function () {
+ $("#status").html("Connecting, please wait...");
+
+ $.get(urlBase + "info", function (data) {
+ $("#status").html("Loading, please wait...");
+
+ Object.keys(data).forEach((key) => {
+ var dtTemplate = $("#infoDtTemplate").clone();
+ var ddTemplate = $("#infoDdTemplate").clone();
+
+ const name = keyToName[key] || key;
+ let value = data[key];
+
+ switch(key) {
+
+ case 'millis':
+ value = `${(value / 1000 / 60).toFixed()} minutes, ${((value / 1000) % 60).toFixed()} seconds`;
+ break;
+
+ case 'flashChipSize':
+ case 'flashChipRealSize':
+ case 'freeHeap':
+ case 'freeSketchSpace':
+ case 'sketchSize':
+ value = `${value.toLocaleString()} bytes`;
+ break;
+
+ case 'cpuFreqMHz':
+ value = `${value}MHz`;
+ break;
+ }
+
+ dtTemplate.html(name);
+ ddTemplate.html(value);
+
+ $("#infoDl").append(dtTemplate);
+ $("#infoDl").append(ddTemplate);
+ });
+ });
+
+ $("#status").html("Ready");
+});
diff --git a/esp8266-fastled-webserver/data/simple.htm b/esp8266-fastled-webserver/data/simple.htm
index 5fc86227..3fe8527f 100644
--- a/esp8266-fastled-webserver/data/simple.htm
+++ b/esp8266-fastled-webserver/data/simple.htm
@@ -47,6 +47,8 @@
+
+
diff --git a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino
index 30f6a85d..2af84642 100644
--- a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino
+++ b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino
@@ -1,6 +1,6 @@
/*
ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
- Copyright (C) 2015-2018 Jason Coon
+ Copyright (C) Jason Coon
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -16,67 +16,24 @@
along with this program. If not, see .
*/
-//#define FASTLED_ALLOW_INTERRUPTS 1
-//#define INTERRUPT_THRESHOLD 1
-#define FASTLED_INTERRUPT_RETRY_COUNT 0
-
-#include
-FASTLED_USING_NAMESPACE
-
-extern "C" {
-#include "user_interface.h"
-}
-
-// #include
-#include
-#define MYFS LittleFS
-
-
-#include
-#include
-#include
-#include
-#include
-//#include
-
-#include
-//#include
-#include // https://github.com/tzapu/WiFiManager/tree/development
-#include "GradientPalettes.h"
-
-#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))
-
-#include "Field.h"
-
-//#define RECV_PIN D4
-//IRrecv irReceiver(RECV_PIN);
-
-//#include "Commands.h"
+#include "common.h"
WiFiManager wifiManager;
ESP8266WebServer webServer(80);
//WebSocketsServer webSocketsServer = WebSocketsServer(81);
ESP8266HTTPUpdateServer httpUpdateServer;
-#include "FSBrowser.h"
-
-#define DATA_PIN D5
-#define LED_TYPE WS2811
-#define COLOR_ORDER RGB
-#define NUM_LEDS 200
-
-#define MILLI_AMPS 2000 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
-#define FRAMES_PER_SECOND 120 // here you can control the speed. With the Access Point / Web Server the animations run a bit slower.
+// Define NTP Client to get time
+WiFiUDP ntpUDP;
+NTPClient timeClient(ntpUDP, "pool.ntp.org", UTC_OFFSET_IN_SECONDS, NTP_UPDATE_THROTTLE_MILLLISECONDS);
String nameString;
-#include "Ping.h"
-
-CRGB leds[NUM_LEDS];
+CRGB leds[NUM_PIXELS];
const uint8_t brightnessCount = 5;
-uint8_t brightnessMap[brightnessCount] = { 16, 32, 64, 128, 255 };
-uint8_t brightnessIndex = 3;
+const uint8_t brightnessMap[brightnessCount] = { 16, 32, 64, 128, 255 };
+uint8_t brightnessIndex = DEFAULT_BRIGHTNESS_INDEX;
// ten seconds per color palette makes a good demo
// 20-120 is better for deployment
@@ -96,10 +53,6 @@ uint8_t speed = 30;
///////////////////////////////////////////////////////////////////////
-// Forward declarations of an array of cpt-city gradient palettes, and
-// a count of how many there are. The actual color palette definitions
-// are at the bottom of this file.
-extern const TProgmemRGBGradientPalettePtr gGradientPalettes[];
uint8_t gCurrentPaletteNumber = 0;
@@ -108,12 +61,15 @@ CRGBPalette16 gTargetPalette( gGradientPalettes[0] );
CRGBPalette16 IceColors_p = CRGBPalette16(CRGB::Black, CRGB::Blue, CRGB::Aqua, CRGB::White);
-uint8_t currentPatternIndex = 0; // Index number of which pattern is current
+uint8_t currentPatternIndex = DEFAULT_PATTERN_INDEX; // Index number of which pattern is current
uint8_t autoplay = 0;
uint8_t autoplayDuration = 10;
unsigned long autoPlayTimeout = 0;
+uint8_t showClock = 0;
+uint8_t clockBackgroundFade = 240;
+
uint8_t currentPaletteIndex = 0;
uint8_t gHue = 0; // rotating "base color" used by many of the patterns
@@ -123,33 +79,136 @@ CRGB solidColor = CRGB::Blue;
// scale the brightness of all pixels down
void dimAll(byte value)
{
- for (int i = 0; i < NUM_LEDS; i++) {
- leds[i].nscale8(value);
+ for (auto led : leds) {
+ led.nscale8(value);
}
}
-typedef void (*Pattern)();
-typedef Pattern PatternList[];
-typedef struct {
- Pattern pattern;
- String name;
-} PatternAndName;
-typedef PatternAndName PatternAndNameList[];
-
-#include "Twinkles.h"
-#include "TwinkleFOX.h"
-#include "PridePlayground.h"
-#include "ColorWavesPlayground.h"
-
// List of patterns to cycle through. Each is defined as a separate function below.
-PatternAndNameList patterns = {
- { pride, "Pride" },
+// NOTE: HAS_POLAR_COORDS implies HAS_COORDINATE_MAP
+// IS_FIBONACCI implies HAS_COORDINATE_MAP
+
+// TODO: Consider patterns listing name and all variants:
+// [] original variant
+// [] fibonacci variant (or nullptr)
+// [] concentric ring variant (or nullptr)
+// [] coordinates variant (or nullptr)
+// WHY #1: Easier to manage defining the patterns via a macro,
+// which discards arguments that do not apply for a given
+// board, than this #if/#endif spaghetti mess.
+// WHY #2: Easier for users to see correlations between the patterns,
+// when switching between them.
+// WHY #3: May eventually be able to change mapping for standard
+// effects (emulating led array, but using custom mapping),
+// which could further reduce code duplication.
+
+const PatternAndName patterns[] = {
+ { pride, "Pride" },
+#if IS_FIBONACCI
+ { prideFibonacci, "Pride Fibonacci" },
+#endif
+
{ colorWaves, "Color Waves" },
+#if HAS_COORDINATE_MAP // really a wrong name... and likely doing way more computation than necessary
+ { radarSweepPalette, "Radar Sweep Palette" },
+#endif
+#if HAS_POLAR_COORDS // really a wrong name... and likely doing way more computation than necessary
+ // noise patterns (Polar variations)
+ { gradientPalettePolarNoise, "Gradient Palette Polar Noise" },
+ { palettePolarNoise, "Palette Polar Noise" },
+ { firePolarNoise, "Fire Polar Noise" },
+ { firePolarNoise2, "Fire Polar Noise 2" },
+ { lavaPolarNoise, "Lava Polar Noise" },
+ { rainbowPolarNoise, "Rainbow Polar Noise" },
+ { rainbowStripePolarNoise, "Rainbow Stripe Polar Noise" },
+ { partyPolarNoise, "Party Polar Noise" },
+ { forestPolarNoise, "Forest Polar Noise" },
+ { cloudPolarNoise, "Cloud Polar Noise" },
+ { oceanPolarNoise, "Ocean Polar Noise" },
+ { blackAndWhitePolarNoise, "Black & White Polar Noise" },
+ { blackAndBluePolarNoise, "Black & Blue Polar Noise" },
+#endif
+
+#if IS_FIBONACCI
+ { colorWavesFibonacci, "Color Waves Fibonacci" },
+
+ { pridePlayground, "Pride Playground" },
+ { pridePlaygroundFibonacci, "Pride Playground Fibonacci" },
+
+ { colorWavesPlayground, "Color Waves Playground" },
+ { colorWavesPlaygroundFibonacci, "Color Waves Playground Fibonacci" },
+#endif
+
+ { wheel, "Wheel" },
+#if (PARALLEL_OUTPUT_CHANNELS > 1)
+ { multi_test, "Multi Test" },
+#endif
+
+#if IS_FIBONACCI
+ { swirlFibonacci, "Swirl Fibonacci"},
+ { fireFibonacci, "Fire Fibonacci" },
+ { waterFibonacci, "Water Fibonacci" },
+ { emitterFibonacci, "Emitter Fibonacci" },
+
+ { pacifica_loop, "Pacifica" },
+ { pacifica_fibonacci_loop, "Pacifica Fibonacci" },
+#endif
+
+#if HAS_COORDINATE_MAP
+ // matrix patterns
+ { anglePalette, "Angle Palette" },
+ { radiusPalette, "Radius Palette" },
+ { xPalette, "X Axis Palette" },
+ { yPalette, "Y Axis Palette" },
+ { xyPalette, "XY Axis Palette" },
+
+ { angleGradientPalette, "Angle Gradient Palette" },
+ { radiusGradientPalette, "Radius Gradient Palette" },
+ { xGradientPalette, "X Axis Gradient Palette" },
+ { yGradientPalette, "Y Axis Gradient Palette" },
+ { xyGradientPalette, "XY Axis Gradient Palette" },
+#endif
+
+#if HAS_COORDINATE_MAP
+ // noise patterns
+ { fireNoise, "Fire Noise" },
+ { fireNoise2, "Fire Noise 2" },
+ { lavaNoise, "Lava Noise" },
+ { rainbowNoise, "Rainbow Noise" },
+ { rainbowStripeNoise, "Rainbow Stripe Noise" },
+ { partyNoise, "Party Noise" },
+ { forestNoise, "Forest Noise" },
+ { cloudNoise, "Cloud Noise" },
+ { oceanNoise, "Ocean Noise" },
+ { blackAndWhiteNoise, "Black & White Noise" },
+ { blackAndBlueNoise, "Black & Blue Noise" },
+#endif
+
+#if IS_FIBONACCI
+ { drawAnalogClock, "Analog Clock" },
+
+ { drawSpiralAnalogClock13, "Spiral Analog Clock 13" },
+ { drawSpiralAnalogClock21, "Spiral Analog Clock 21" },
+ { drawSpiralAnalogClock34, "Spiral Analog Clock 34" },
+ { drawSpiralAnalogClock55, "Spiral Analog Clock 55" },
+ { drawSpiralAnalogClock89, "Spiral Analog Clock 89" },
+
+ { drawSpiralAnalogClock21and34, "Spiral Analog Clock 21 & 34"},
+ { drawSpiralAnalogClock13_21_and_34, "Spiral Analog Clock 13, 21 & 34"},
+ { drawSpiralAnalogClock34_21_and_13, "Spiral Analog Clock 34, 21 & 13"},
+#endif
+
{ pridePlayground, "Pride Playground" },
{ colorWavesPlayground, "Color Waves Playground" },
+#if defined(PRODUCT_KRAKEN64)
+ // Kraken patterns ... these use body[], which is also used as a proxy for radius...
+ { radiusPalette, "Kraken Palette" },
+ { radiusGradientPalette, "Kraken Gradient Palette" },
+#endif
+
// twinkle patterns
{ rainbowTwinkles, "Rainbow Twinkles" },
{ snowTwinkles, "Snow Twinkles" },
@@ -182,16 +241,12 @@ PatternAndNameList patterns = {
{ fire, "Fire" },
{ water, "Water" },
- { showSolidColor, "Solid Color" }
-};
+ { strandTest, "Strand Test" },
-const uint8_t patternCount = ARRAY_SIZE(patterns);
+ { showSolidColor, "Solid Color" } // This *must* be the last pattern
+};
-typedef struct {
- CRGBPalette16 palette;
- String name;
-} PaletteAndName;
-typedef PaletteAndName PaletteAndNameList[];
+const uint8_t patternCount = ARRAY_SIZE2(patterns);
const CRGBPalette16 palettes[] = {
RainbowColors_p,
@@ -204,7 +259,7 @@ const CRGBPalette16 palettes[] = {
HeatColors_p
};
-const uint8_t paletteCount = ARRAY_SIZE(palettes);
+const uint8_t paletteCount = ARRAY_SIZE2(palettes);
const String paletteNames[paletteCount] = {
"Rainbow",
@@ -217,7 +272,11 @@ const String paletteNames[paletteCount] = {
"Heat",
};
-#include "Fields.h"
+// TODO / BUGBUG -- should this be ESP8266-specific? Is this only for when IR enabled ???
+// FIB128 did not have this...
+#if defined(PRODUCT_FIBONACCI256)
+ ADC_MODE(ADC_VCC);
+#endif
void setup() {
WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
@@ -226,23 +285,50 @@ void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
- FastLED.addLeds(leds, NUM_LEDS); // for WS2812 (Neopixel)
- //FastLED.addLeds(leds, NUM_LEDS); // for APA102 (Dotstar)
+ uint16_t milliAmps = (AVAILABLE_MILLI_AMPS < MAX_MILLI_AMPS) ? AVAILABLE_MILLI_AMPS : MAX_MILLI_AMPS;
+
+ #if PARALLEL_OUTPUT_CHANNELS == 1
+ FastLED.addLeds(leds, NUM_PIXELS); // for WS2812 (Neopixel)
+ #else
+ #if PARALLEL_OUTPUT_CHANNELS >= 2
+ FastLED.addLeds(leds, LedOffset<1>(), LedCount<1>());
+ FastLED.addLeds(leds, LedOffset<2>(), LedCount<2>());
+ #endif
+ #if PARALLEL_OUTPUT_CHANNELS >= 3
+ FastLED.addLeds(leds, LedOffset<3>(), LedCount<3>());
+ #endif
+ #if PARALLEL_OUTPUT_CHANNELS >= 4
+ FastLED.addLeds(leds, LedOffset<4>(), LedCount<4>());
+ #endif
+ #if PARALLEL_OUTPUT_CHANNELS >= 5
+ FastLED.addLeds(leds, LedOffset<5>(), LedCount<4>());
+ #endif
+ #if PARALLEL_OUTPUT_CHANNELS >= 6
+ FastLED.addLeds(leds, LedOffset<6>(), LedCount<4>());
+ #endif
+ #endif // PARALLEL_OUTPUT_CHANNELS
+
+ //FastLED.addLeds(leds, NUM_PIXELS); // for APA102 (Dotstar)
+
FastLED.setDither(false);
FastLED.setCorrection(TypicalLEDStrip);
FastLED.setBrightness(brightness);
- FastLED.setMaxPowerInVoltsAndMilliamps(5, MILLI_AMPS);
- fill_solid(leds, NUM_LEDS, CRGB::Black);
+ FastLED.setMaxPowerInVoltsAndMilliamps(5, milliAmps);
+ fill_solid(leds, NUM_PIXELS, CRGB::Black);
FastLED.show();
- EEPROM.begin(512);
+ EEPROM.begin(512); // TODO: move settings (currently EEPROM) to fields.hpp/.cpp
readSettings();
FastLED.setBrightness(brightness);
- // irReceiver.enableIRIn(); // Start the receiver
+#if defined(ENABLE_IR)
+ irReceiver.enableIRIn(); // Start the receiver
+#endif
Serial.println();
+ Serial.println(F("System Info:"));
+ Serial.print( F("Max mA: ") ); Serial.println(milliAmps);
Serial.print( F("Heap: ") ); Serial.println(system_get_free_heap_size());
Serial.print( F("Boot Vers: ") ); Serial.println(system_get_boot_version());
Serial.print( F("CPU: ") ); Serial.println(system_get_cpu_freq());
@@ -254,6 +340,21 @@ void setup() {
Serial.print( F("MAC Address: ") ); Serial.println(WiFi.macAddress());
Serial.println();
+ Serial.println(F("Settings: "));
+ Serial.print(F("brightness: ")); Serial.println(brightness);
+ Serial.print(F("currentPatternIndex: ")); Serial.println(currentPatternIndex);
+ Serial.print(F("solidColor.r: ")); Serial.println(solidColor.r);
+ Serial.print(F("solidColor.g: ")); Serial.println(solidColor.g);
+ Serial.print(F("solidColor.b: ")); Serial.println(solidColor.b);
+ Serial.print(F("power: ")); Serial.println(power);
+ Serial.print(F("autoplay: ")); Serial.println(autoplay);
+ Serial.print(F("autoplayDuration: ")); Serial.println(autoplayDuration);
+ Serial.print(F("currentPaletteIndex: ")); Serial.println(currentPaletteIndex);
+ Serial.print(F("showClock: ")); Serial.println(showClock);
+ Serial.print(F("clockBackgroundFade: ")); Serial.println(clockBackgroundFade);
+ Serial.println();
+
+
if (!MYFS.begin()) {
Serial.println(F("An error occurred when attempting to mount the flash file system"));
} else {
@@ -268,6 +369,7 @@ void setup() {
Serial.printf("\n");
}
+
// Do a little work to get a unique-ish name. Get the
// last two bytes of the MAC (HEX'd)":
@@ -283,12 +385,23 @@ void setup() {
String macIdString = macID;
macIdString.toUpperCase();
- nameString = "ESP8266-" + macIdString;
-
- char nameChar[nameString.length() + 1];
- memset(nameChar, 0, nameString.length() + 1);
-
- for (unsigned int i = 0; i < nameString.length(); i++) {
+ nameString = NAME_PREFIX + macIdString;
+
+ // Allocation of variable-sized arrays on the stack is a GCC extension.
+ // Converting this to be compile-time evaluated is possible:
+ // nameString.length() === strlen(NAME_PREFIX) + strlen(maxIdString)
+ // strlen(NAME_PREFIX) is compile-time constexpr (but changes per NAME_PREFIX)
+ // strlen(macIdString) is always 4
+ // Therefore, can use the following to ensure statically evaluated at compile-time,
+ // and avoid use of GCC extensions, with no performance loss.
+ const size_t nameCharCount = static_eval::value;
+ const size_t nameBufferSize = static_eval::value;
+ char nameChar[nameBufferSize];
+ memset(nameChar, 0, nameBufferSize);
+ // Technically, this should *NEVER* need to check the nameString length.
+ // However, I prefer to code defensively, since no static_assert() can detect this.
+ size_t loopUntil = (nameCharCount <= nameString.length() ? nameCharCount : nameString.length());
+ for (size_t i = 0; i < loopUntil; i++) {
nameChar[i] = nameString.charAt(i);
}
@@ -311,14 +424,26 @@ void setup() {
httpUpdateServer.setup(&webServer);
webServer.on("/all", HTTP_GET, []() {
- String json = getFieldsJson(fields, fieldCount);
+ String json = getFieldsJson();
+ webServer.sendHeader("Access-Control-Allow-Origin", "*");
+ webServer.send(200, "application/json", json);
+ });
+
+ webServer.on("/product", HTTP_GET, []() {
+ String json = "{\"productName\":\"" PRODUCT_FRIENDLY_NAME "\"}";
+ webServer.sendHeader("Access-Control-Allow-Origin", "*");
+ webServer.send(200, "application/json", json);
+ });
+
+ webServer.on("/info", HTTP_GET, []() {
+ String json = getInfoJson();
webServer.sendHeader("Access-Control-Allow-Origin", "*");
webServer.send(200, "application/json", json);
});
webServer.on("/fieldValue", HTTP_GET, []() {
String name = webServer.arg("name");
- String value = getFieldValue(name, fields, fieldCount);
+ String value = getFieldValue(name);
webServer.sendHeader("Access-Control-Allow-Origin", "*");
webServer.send(200, "text/json", value);
});
@@ -326,7 +451,7 @@ void setup() {
webServer.on("/fieldValue", HTTP_POST, []() {
String name = webServer.arg("name");
String value = webServer.arg("value");
- String newValue = setFieldValue(name, value, fields, fieldCount);
+ String newValue = setFieldValue(name, value);
webServer.sendHeader("Access-Control-Allow-Origin", "*");
webServer.send(200, "text/json", newValue);
});
@@ -341,7 +466,6 @@ void setup() {
webServer.on("/cooling", HTTP_POST, []() {
String value = webServer.arg("value");
cooling = value.toInt();
- writeAndCommitSettings();
broadcastInt("cooling", cooling);
webServer.sendHeader("Access-Control-Allow-Origin", "*");
sendInt(cooling);
@@ -350,7 +474,6 @@ void setup() {
webServer.on("/sparking", HTTP_POST, []() {
String value = webServer.arg("value");
sparking = value.toInt();
- writeAndCommitSettings();
broadcastInt("sparking", sparking);
webServer.sendHeader("Access-Control-Allow-Origin", "*");
sendInt(sparking);
@@ -466,6 +589,30 @@ void setup() {
sendInt(autoplayDuration);
});
+ webServer.on("/showClock", HTTP_POST, []() {
+ String value = webServer.arg("value");
+ long tmp = value.toInt();
+ if (tmp < 0) {
+ tmp = 0;
+ } else if (tmp > 1) {
+ tmp = 1;
+ }
+ setShowClock(tmp);
+ sendInt(showClock);
+ });
+
+ webServer.on("/clockBackgroundFade", HTTP_POST, []() {
+ String value = webServer.arg("value");
+ long tmp = value.toInt();
+ if (tmp < 0) {
+ tmp = 0;
+ } else if (tmp > 255) {
+ tmp = 255;
+ }
+ setClockBackgroundFade(tmp);
+ sendInt(clockBackgroundFade);
+ });
+
//list directory
webServer.on("/list", HTTP_GET, handleFileList);
//load editor
@@ -496,6 +643,7 @@ void setup() {
// Serial.println("Web socket server started");
autoPlayTimeout = millis() + (autoplayDuration * 1000);
+ timeClient.begin();
}
void sendInt(uint8_t value)
@@ -520,8 +668,15 @@ void broadcastString(String name, String value)
// webSocketsServer.broadcastTXT(json);
}
+// TODO: Add board-specific entropy sources
+// e.g., using `uint32_t esp_random()`, if exposed in Arduino ESP32 / ESP8266 BSPs
+// e.g., directly reading from 0x3FF20E44 on ESP8266 (dangerous! no entropy validation, whitening)
+// e.g., directly reading from 0x3FF75144 on ESP32 (dangerous! no entropy validation, whitening)
+// e.g., directly reading from RANDOM_REG32 (dangerous! no entropy validation, whitening)
+// e.g., using a library, such as https://github.com/marvinroger/ESP8266TrueRandom/blob/master/ESP8266TrueRandom.cpp (less dangerous?)
+// e.g., directly reading REG_READ(WDEV_RND_REG) (dangerous! no check for sufficient clock cycles passed for entropy)
void loop() {
- // Add entropy to random number generator; we use a lot of it.
+ // Modify random number generator seed; we use a lot of it. (Note: this is still deterministic)
random16_add_entropy(random(65535));
// webSocketsServer.loop();
@@ -530,9 +685,8 @@ void loop() {
webServer.handleClient();
MDNS.update();
- // timeClient.update();
-
static bool hasConnected = false;
+
EVERY_N_SECONDS(1) {
if (WiFi.status() != WL_CONNECTED) {
// Serial.printf("Connecting to %s\n", ssid);
@@ -549,17 +703,17 @@ void loop() {
Serial.print(" or http://");
Serial.print(nameString);
Serial.println(".local in your browser");
+ } else {
+ timeClient.update(); // NTPClient has throttling built-in
}
}
checkPingTimer();
-
- // handleIrInput();
+ handleIrInput(); // empty function when ENABLE_IR is not defined
if (power == 0) {
- fill_solid(leds, NUM_LEDS, CRGB::Black);
- FastLED.show();
- delay(1000 / FRAMES_PER_SECOND);
+ fill_solid(leds, NUM_PIXELS, CRGB::Black);
+ FastLED.delay(1000 / FRAMES_PER_SECOND); // this function calls FastLED.show() at least once
return;
}
@@ -587,9 +741,11 @@ void loop() {
// Call the current pattern function once, updating the 'leds' array
patterns[currentPatternIndex].pattern();
- FastLED.show();
+ #if IS_FIBONACCI
+ if (showClock) drawAnalogClock();
+ #endif
- // insert a delay to keep the framerate modest
+ // insert a delay to keep the framerate modest ... this is guaranteed to call FastLED.show() at least once
FastLED.delay(1000 / FRAMES_PER_SECOND);
}
@@ -630,219 +786,15 @@ void loop() {
// }
//}
-//void handleIrInput()
-//{
-// InputCommand command = readCommand();
-//
-// if (command != InputCommand::None) {
-// Serial.print("command: ");
-// Serial.println((int) command);
-// }
-//
-// switch (command) {
-// case InputCommand::Up: {
-// adjustPattern(true);
-// break;
-// }
-// case InputCommand::Down: {
-// adjustPattern(false);
-// break;
-// }
-// case InputCommand::Power: {
-// setPower(power == 0 ? 1 : 0);
-// break;
-// }
-// case InputCommand::BrightnessUp: {
-// adjustBrightness(true);
-// break;
-// }
-// case InputCommand::BrightnessDown: {
-// adjustBrightness(false);
-// break;
-// }
-// case InputCommand::PlayMode: { // toggle pause/play
-// setAutoplay(!autoplay);
-// break;
-// }
-//
-// // pattern buttons
-//
-// case InputCommand::Pattern1: {
-// setPattern(0);
-// break;
-// }
-// case InputCommand::Pattern2: {
-// setPattern(1);
-// break;
-// }
-// case InputCommand::Pattern3: {
-// setPattern(2);
-// break;
-// }
-// case InputCommand::Pattern4: {
-// setPattern(3);
-// break;
-// }
-// case InputCommand::Pattern5: {
-// setPattern(4);
-// break;
-// }
-// case InputCommand::Pattern6: {
-// setPattern(5);
-// break;
-// }
-// case InputCommand::Pattern7: {
-// setPattern(6);
-// break;
-// }
-// case InputCommand::Pattern8: {
-// setPattern(7);
-// break;
-// }
-// case InputCommand::Pattern9: {
-// setPattern(8);
-// break;
-// }
-// case InputCommand::Pattern10: {
-// setPattern(9);
-// break;
-// }
-// case InputCommand::Pattern11: {
-// setPattern(10);
-// break;
-// }
-// case InputCommand::Pattern12: {
-// setPattern(11);
-// break;
-// }
-//
-// // custom color adjustment buttons
-//
-// case InputCommand::RedUp: {
-// solidColor.red += 8;
-// setSolidColor(solidColor);
-// break;
-// }
-// case InputCommand::RedDown: {
-// solidColor.red -= 8;
-// setSolidColor(solidColor);
-// break;
-// }
-// case InputCommand::GreenUp: {
-// solidColor.green += 8;
-// setSolidColor(solidColor);
-// break;
-// }
-// case InputCommand::GreenDown: {
-// solidColor.green -= 8;
-// setSolidColor(solidColor);
-// break;
-// }
-// case InputCommand::BlueUp: {
-// solidColor.blue += 8;
-// setSolidColor(solidColor);
-// break;
-// }
-// case InputCommand::BlueDown: {
-// solidColor.blue -= 8;
-// setSolidColor(solidColor);
-// break;
-// }
-//
-// // color buttons
-//
-// case InputCommand::Red: {
-// setSolidColor(CRGB::Red);
-// break;
-// }
-// case InputCommand::RedOrange: {
-// setSolidColor(CRGB::OrangeRed);
-// break;
-// }
-// case InputCommand::Orange: {
-// setSolidColor(CRGB::Orange);
-// break;
-// }
-// case InputCommand::YellowOrange: {
-// setSolidColor(CRGB::Goldenrod);
-// break;
-// }
-// case InputCommand::Yellow: {
-// setSolidColor(CRGB::Yellow);
-// break;
-// }
-//
-// case InputCommand::Green: {
-// setSolidColor(CRGB::Green);
-// break;
-// }
-// case InputCommand::Lime: {
-// setSolidColor(CRGB::Lime);
-// break;
-// }
-// case InputCommand::Aqua: {
-// setSolidColor(CRGB::Aqua);
-// break;
-// }
-// case InputCommand::Teal: {
-// setSolidColor(CRGB::Teal);
-// break;
-// }
-// case InputCommand::Navy: {
-// setSolidColor(CRGB::Navy);
-// break;
-// }
-//
-// case InputCommand::Blue: {
-// setSolidColor(CRGB::Blue);
-// break;
-// }
-// case InputCommand::RoyalBlue: {
-// setSolidColor(CRGB::RoyalBlue);
-// break;
-// }
-// case InputCommand::Purple: {
-// setSolidColor(CRGB::Purple);
-// break;
-// }
-// case InputCommand::Indigo: {
-// setSolidColor(CRGB::Indigo);
-// break;
-// }
-// case InputCommand::Magenta: {
-// setSolidColor(CRGB::Magenta);
-// break;
-// }
-//
-// case InputCommand::White: {
-// setSolidColor(CRGB::White);
-// break;
-// }
-// case InputCommand::Pink: {
-// setSolidColor(CRGB::Pink);
-// break;
-// }
-// case InputCommand::LightPink: {
-// setSolidColor(CRGB::LightPink);
-// break;
-// }
-// case InputCommand::BabyBlue: {
-// setSolidColor(CRGB::CornflowerBlue);
-// break;
-// }
-// case InputCommand::LightBlue: {
-// setSolidColor(CRGB::LightBlue);
-// break;
-// }
-// }
-//}
+// TODO: Save settings in file system, not EEPROM!
+const uint8_t SETTINGS_MAGIC_BYTE = 0x96;
void readSettings()
{
// check for "magic number" so we know settings have been written to EEPROM
// and it's not just full of random bytes
- if (EEPROM.read(511) != 55) {
+ if (EEPROM.read(511) != SETTINGS_MAGIC_BYTE) {
return;
}
@@ -882,10 +834,11 @@ void readSettings()
sparking = EEPROM.read(12);
coolLikeIncandescent = EEPROM.read(13);
-}
-void writeAndCommitSettings()
-{
+ showClock = EEPROM.read(14);
+ clockBackgroundFade = EEPROM.read(15);
+}
+void writeAndCommitSettings() {
EEPROM.write(0, brightness);
EEPROM.write(1, currentPatternIndex);
EEPROM.write(2, solidColor.r);
@@ -899,8 +852,10 @@ void writeAndCommitSettings()
EEPROM.write(10, twinkleDensity);
EEPROM.write(11, cooling);
EEPROM.write(12, sparking);
-
- EEPROM.write(511, 55);
+ EEPROM.write(13, coolLikeIncandescent);
+ EEPROM.write(14, showClock);
+ EEPROM.write(15, clockBackgroundFade);
+ EEPROM.write(511, SETTINGS_MAGIC_BYTE);
EEPROM.commit();
}
@@ -908,9 +863,8 @@ void setPower(uint8_t value)
{
power = value == 0 ? 0 : 1;
writeAndCommitSettings();
- broadcastInt("power", power);
+ broadcastInt("power", value);
}
-
void setAutoplay(uint8_t value)
{
autoplay = value == 0 ? 0 : 1;
@@ -1030,23 +984,23 @@ void setBrightness(uint8_t value)
void strandTest()
{
- static uint8_t i = 0;
+ static size_t i = 0;
EVERY_N_SECONDS(1)
{
i++;
- if (i >= NUM_LEDS)
+ if (i >= NUM_PIXELS)
i = 0;
}
- fill_solid(leds, NUM_LEDS, CRGB::Black);
+ fill_solid(leds, NUM_PIXELS, CRGB::Black);
leds[i] = solidColor;
}
void showSolidColor()
{
- fill_solid(leds, NUM_LEDS, solidColor);
+ fill_solid(leds, NUM_PIXELS, solidColor);
}
// Patterns from FastLED example DemoReel100: https://github.com/FastLED/FastLED/blob/master/examples/DemoReel100/DemoReel100.ino
@@ -1054,7 +1008,7 @@ void showSolidColor()
void rainbow()
{
// FastLED's built-in rainbow generator
- fill_rainbow( leds, NUM_LEDS, gHue, 255 / NUM_LEDS);
+ fill_rainbow( leds, NUM_PIXELS, gHue, 255 / NUM_PIXELS);
}
void rainbowWithGlitter()
@@ -1066,14 +1020,14 @@ void rainbowWithGlitter()
void rainbowSolid()
{
- fill_solid(leds, NUM_LEDS, CHSV(gHue, 255, 255));
+ fill_solid(leds, NUM_PIXELS, CHSV(gHue, 255, 255));
}
void confetti()
{
// random colored speckles that blink in and fade smoothly
- fadeToBlackBy( leds, NUM_LEDS, 10);
- int pos = random16(NUM_LEDS);
+ fadeToBlackBy( leds, NUM_PIXELS, 10);
+ int pos = random16(NUM_PIXELS);
// leds[pos] += CHSV( gHue + random8(64), 200, 255);
leds[pos] += ColorFromPalette(palettes[currentPaletteIndex], gHue + random8(64));
}
@@ -1081,8 +1035,8 @@ void confetti()
void sinelon()
{
// a colored dot sweeping back and forth, with fading trails
- fadeToBlackBy( leds, NUM_LEDS, 20);
- int pos = beatsin16(speed, 0, NUM_LEDS);
+ fadeToBlackBy( leds, NUM_PIXELS, 20);
+ int pos = beatsin16(speed, 0, NUM_PIXELS);
static int prevpos = 0;
CRGB color = ColorFromPalette(palettes[currentPaletteIndex], gHue, 255);
if ( pos < prevpos ) {
@@ -1098,7 +1052,7 @@ void bpm()
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
uint8_t beat = beatsin8( speed, 64, 255);
CRGBPalette16 palette = palettes[currentPaletteIndex];
- for ( int i = 0; i < NUM_LEDS; i++) {
+ for ( int i = 0; i < NUM_PIXELS; i++) {
leds[i] = ColorFromPalette(palette, gHue + (i * 2), beat - gHue + (i * 10));
}
}
@@ -1129,10 +1083,10 @@ void juggle()
// Several colored dots, weaving in and out of sync with each other
curhue = thishue; // Reset the hue values.
- fadeToBlackBy(leds, NUM_LEDS, faderate);
+ fadeToBlackBy(leds, NUM_PIXELS, faderate);
for ( int i = 0; i < numdots; i++) {
//beat16 is a FastLED 3.1 function
- leds[beatsin16(basebeat + i + numdots, 0, NUM_LEDS)] += CHSV(gHue + curhue, thissat, thisbright);
+ leds[beatsin16(basebeat + i + numdots, 0, NUM_PIXELS)] += CHSV(gHue + curhue, thissat, thisbright);
curhue += hueinc;
}
}
@@ -1150,7 +1104,7 @@ void water()
// Pride2015 by Mark Kriegsman: https://gist.github.com/kriegsman/964de772d64c502760e5
// This function draws rainbows with an ever-changing,
// widely-varying set of parameters.
-void pride()
+void fillWithPride(bool useFibonacciOrder)
{
static uint16_t sPseudotime = 0;
static uint16_t sLastMillis = 0;
@@ -1171,7 +1125,7 @@ void pride()
sHue16 += deltams * beatsin88( 400, 5, 9);
uint16_t brightnesstheta16 = sPseudotime;
- for ( uint16_t i = 0 ; i < NUM_LEDS; i++) {
+ for ( uint16_t i = 0 ; i < NUM_PIXELS; i++) {
hue16 += hueinc16;
uint8_t hue8 = hue16 / 256;
@@ -1185,40 +1139,91 @@ void pride()
CRGB newcolor = CHSV( hue8, sat8, bri8);
uint16_t pixelnumber = i;
- pixelnumber = (NUM_LEDS - 1) - pixelnumber;
+
+#if IS_FIBONACCI
+ if (useFibonacciOrder) pixelnumber = fibonacciToPhysical[i];
+#else
+ (void)useFibonacciOrder; // unused parameter
+#endif
+
+ pixelnumber = (NUM_PIXELS - 1) - pixelnumber;
nblend( leds[pixelnumber], newcolor, 64);
}
}
+void pride() {
+ fillWithPride(false);
+}
+#if IS_FIBONACCI // prideFibonacci() uses fibonacciToPhysical
+void prideFibonacci() {
+ fillWithPride(true);
+}
+#endif
-void radialPaletteShift()
+void fillRadialPaletteShift(bool useFibonacciOrder)
{
- for (uint16_t i = 0; i < NUM_LEDS; i++) {
- // leds[i] = ColorFromPalette( gCurrentPalette, gHue + sin8(i*16), brightness);
- leds[i] = ColorFromPalette(gCurrentPalette, i + gHue, 255, LINEARBLEND);
+ for (uint16_t i = 0; i < NUM_PIXELS; i++) {
+ #if IS_FIBONACCI
+ uint16_t idx = useFibonacciOrder ? fibonacciToPhysical[i] : i;
+ #else
+ (void)useFibonacciOrder;
+ uint16_t idx = i;
+ #endif
+ leds[idx] = ColorFromPalette(gCurrentPalette, i + gHue, 255, LINEARBLEND);
}
}
+void fillRadialPaletteShiftOutward(bool useFibonacciOrder)
+{
+ for (uint16_t i = 0; i < NUM_PIXELS; i++) {
+ #if IS_FIBONACCI
+ uint16_t idx = useFibonacciOrder ? fibonacciToPhysical[i] : i;
+ #else
+ (void)useFibonacciOrder;
+ uint16_t idx = i;
+ #endif
+ leds[idx] = ColorFromPalette(gCurrentPalette, i - gHue, 255, LINEARBLEND);
+ }
+}
+// TODO: define function radialPaletteShiftFibonacci()
+void radialPaletteShift()
+{
+ #if IS_FIBONACCI
+ fillRadialPaletteShift(true);
+ #else
+ fillRadialPaletteShift(false);
+ #endif
+}
+// TODO: define function radialPaletteShiftOutwardFibonacci(), and update to call corresponding function
+void radialPaletteShiftOutward()
+{
+ #if IS_FIBONACCI
+ fillRadialPaletteShiftOutward(true);
+ #else
+ fillRadialPaletteShiftOutward(false);
+ #endif
+}
+
// based on FastLED example Fire2012WithPalette: https://github.com/FastLED/FastLED/blob/master/examples/Fire2012WithPalette/Fire2012WithPalette.ino
-void heatMap(CRGBPalette16 palette, bool up)
+void heatMap(const CRGBPalette16& palette, bool up)
{
- fill_solid(leds, NUM_LEDS, CRGB::Black);
+ fill_solid(leds, NUM_PIXELS, CRGB::Black);
- // Add entropy to random number generator; we use a lot of it.
+ // Modify random number generator seed; we use a lot of it. (Note: this is still deterministic)
random16_add_entropy(random(256));
// Array of temperature readings at each simulation cell
- static byte heat[NUM_LEDS];
+ static byte heat[NUM_PIXELS];
byte colorindex;
// Step 1. Cool down every cell a little
- for ( uint16_t i = 0; i < NUM_LEDS; i++) {
- heat[i] = qsub8( heat[i], random8(0, ((cooling * 10) / NUM_LEDS) + 2));
+ for ( uint16_t i = 0; i < NUM_PIXELS; i++) {
+ heat[i] = qsub8( heat[i], random8(0, ((cooling * 10) / NUM_PIXELS) + 2));
}
// Step 2. Heat from each cell drifts 'up' and diffuses a little
- for ( uint16_t k = NUM_LEDS - 1; k >= 2; k--) {
+ for ( uint16_t k = NUM_PIXELS - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2] ) / 3;
}
@@ -1229,7 +1234,7 @@ void heatMap(CRGBPalette16 palette, bool up)
}
// Step 4. Map from heat cells to LED colors
- for ( uint16_t j = 0; j < NUM_LEDS; j++) {
+ for ( uint16_t j = 0; j < NUM_PIXELS; j++) {
// Scale the heat value from 0-255 down to 0-240
// for best results with color palettes.
colorindex = scale8(heat[j], 190);
@@ -1240,7 +1245,7 @@ void heatMap(CRGBPalette16 palette, bool up)
leds[j] = color;
}
else {
- leds[(NUM_LEDS - 1) - j] = color;
+ leds[(NUM_PIXELS - 1) - j] = color;
}
}
}
@@ -1248,18 +1253,12 @@ void heatMap(CRGBPalette16 palette, bool up)
void addGlitter( uint8_t chanceOfGlitter)
{
if ( random8() < chanceOfGlitter) {
- leds[ random16(NUM_LEDS) ] += CRGB::White;
+ leds[ random16(NUM_PIXELS) ] += CRGB::White;
}
}
///////////////////////////////////////////////////////////////////////
-// Forward declarations of an array of cpt-city gradient palettes, and
-// a count of how many there are. The actual color palette definitions
-// are at the bottom of this file.
-extern const TProgmemRGBGradientPalettePtr gGradientPalettes[];
-extern const uint8_t gGradientPaletteCount;
-
uint8_t beatsaw8( accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest = 255,
uint32_t timebase = 0, uint8_t phase_offset = 0)
{
@@ -1271,15 +1270,11 @@ uint8_t beatsaw8( accum88 beats_per_minute, uint8_t lowest = 0, uint8_t highest
return result;
}
-void colorWaves()
-{
- colorwaves( leds, NUM_LEDS, gCurrentPalette);
-}
// ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb
// This function draws color waves with an ever-changing,
// widely-varying set of parameters, using a color palette.
-void colorwaves( CRGB* ledarray, uint16_t numleds, CRGBPalette16& palette)
+void fillWithColorwaves( CRGB* ledarray, uint16_t numleds, const CRGBPalette16& palette, bool useFibonacciOrder)
{
static uint16_t sPseudotime = 0;
static uint16_t sLastMillis = 0;
@@ -1324,17 +1319,220 @@ void colorwaves( CRGB* ledarray, uint16_t numleds, CRGBPalette16& palette)
CRGB newcolor = ColorFromPalette( palette, index, bri8);
uint16_t pixelnumber = i;
+#if IS_FIBONACCI
+ if (useFibonacciOrder) pixelnumber = fibonacciToPhysical[i];
+#else
+ (void)useFibonacciOrder;
+#endif
pixelnumber = (numleds - 1) - pixelnumber;
nblend( ledarray[pixelnumber], newcolor, 128);
}
}
+void colorWaves()
+{
+ fillWithColorwaves( leds, NUM_PIXELS, gCurrentPalette, false);
+}
+#if IS_FIBONACCI // colorWavesFibonacci() uses fibonacciToPhysical
+void colorWavesFibonacci()
+{
+ fillWithColorwaves( leds, NUM_PIXELS, gCurrentPalette, true);
+}
+#endif
+
// Alternate rendering function just scrolls the current palette
// across the defined LED strip.
void palettetest( CRGB* ledarray, uint16_t numleds, const CRGBPalette16& gCurrentPalette)
{
static uint8_t startindex = 0;
startindex--;
- fill_palette( ledarray, numleds, startindex, (256 / NUM_LEDS) + 1, gCurrentPalette, 255, LINEARBLEND);
+ fill_palette( ledarray, numleds, startindex, (256 / NUM_PIXELS) + 1, gCurrentPalette, 255, LINEARBLEND);
+}
+
+#if IS_FIBONACCI // swirlFibonacci() uses physicalToFibonacci and angles
+void swirlFibonacci() {
+
+ const float z = 2.5; // zoom (2.0)
+ const float w = 3.0; // number of wings (3)
+ const float p_min = 0.1; const float p_max = 2.0; // puff up (default: 1.0)
+ const float d_min = 0.1; const float d_max = 2.0; // dent (default: 0.5)
+ const float s_min = -3.0; const float s_max = 2.0; // swirl (default: -2.0)
+ const float g_min = 0.1; const float g_max = 0.5; // glow (default: 0.2)
+ const float b = 240; // inverse brightness (240)
+
+ const float p = p_min + beatsin88(13*speed) / (float)UINT16_MAX * (p_max - p_min);
+ const float d = d_min + beatsin88(17*speed) / (float)UINT16_MAX * (d_max - d_min);
+ const float s = s_min + beatsin88(7*speed) / (float)UINT16_MAX * (s_max - s_min);
+ const float g = g_min + beatsin88(27*speed) / (float)UINT16_MAX * (g_max - g_min);
+
+ CRGBPalette16 palette( gGradientPalettes[1] ); // es_rivendell_15_gp
+
+ for (uint16_t i = 0; i < NUM_PIXELS; i++) {
+ float r = physicalToFibonacci[i] / 256.0 * z;
+ float a = (angles[i] + (beat88(3*speed)>>3)) / 256.0 * TWO_PI;
+ float v = r - p + d * sin(w * a + s * r * r);
+ float c = 255 - b * pow(fabs(v), g);
+ if (c < 0) c = 0;
+ else if (c > 255) c = 255;
+
+ leds[i] = ColorFromPalette(palette, (uint8_t)c);
+ }
+}
+#endif
+
+#if IS_FIBONACCI // fireFibonacci() uses coordsX/coordsY
+// TODO: combine with normal fire effect
+void fireFibonacci() {
+ for (uint16_t i = 0; i < NUM_PIXELS; i++) {
+ uint16_t x = coordsX[i];
+ uint16_t y = coordsY[i];
+
+ uint8_t n = qsub8( inoise8((x << 2) - beat88(speed << 2), (y << 2)), x );
+
+ leds[i] = ColorFromPalette(HeatColors_p, n);
+ }
+}
+#endif
+
+#if IS_FIBONACCI // waterFibonacci() uses coordsX/coordsY
+// TODO: combine with normal water effect
+void waterFibonacci() {
+ for (uint16_t i = 0; i < NUM_PIXELS; i++) {
+ uint16_t x = coordsX[i];
+ uint16_t y = coordsY[i];
+
+ uint8_t n = inoise8((x << 2) + beat88(speed << 2), (y << 4));
+
+ leds[i] = ColorFromPalette(IceColors_p, n);
+ }
+}
+#endif
+
+#if IS_FIBONACCI // emitterFibonacci() uses angle, antialiasPixelAR()
+/**
+ * Emits arcs of color spreading out from the center to the edge of the disc.
+ */
+void emitterFibonacci() {
+ static CRGB ledBuffer[NUM_PIXELS]; // buffer for better fade behavior
+ const uint8_t dAngle = 32; // angular span of the traces
+ const uint8_t dRadius = 12; // radial width of the traces
+ const uint8_t vSpeed = 16; // max speed variation
+
+
+ static const uint8_t eCount = 7; // Number of simultanious traces
+ static uint8_t angle[eCount]; // individual trace angles
+ static uint16_t timeOffset[eCount]; // individual offsets from beat8() function
+ static uint8_t speedOffset[eCount]; // individual speed offsets limited by vSpeed
+ static uint8_t sparkIdx = 0; // randomizer cycles through traces to spark new ones
+
+ // spark new trace
+ EVERY_N_MILLIS(20) {
+ if (random8(17) <= (speed >> 4)) { // increase change rate for higher speeds
+ angle[sparkIdx] = random8();
+ speedOffset[sparkIdx] = random8(vSpeed); // individual speed variation
+ timeOffset[sparkIdx] = beat8(qadd8(speed,speedOffset[sparkIdx]));
+ sparkIdx = addmod8(sparkIdx, 1, eCount); // continue randomizer at next spark
+ }
+ }
+
+ // fade traces
+ fadeToBlackBy( ledBuffer, NUM_PIXELS, 6 + (speed >> 3));
+
+ // draw traces
+ for (uint8_t e = 0; e < eCount; e++) {
+ uint8_t startRadius = sub8(beat8(qadd8(speed, speedOffset[e])), timeOffset[e]);
+ uint8_t endRadius = add8(startRadius, dRadius + (speed>>5)); // increase radial width for higher speeds
+ antialiasPixelAR(angle[e], dAngle, startRadius, endRadius, ColorFromPalette(gCurrentPalette, startRadius), ledBuffer);
+ }
+
+ // copy buffer to actual strip
+ memcpy(leds, ledBuffer, sizeof(ledBuffer[0])*NUM_PIXELS);
+}
+#endif
+
+void wheel() {
+ for (uint16_t i = 0; i < NUM_PIXELS; i++) {
+ uint8_t j = beat8(speed);
+ uint8_t hue = i + j;
+ leds[i] = CHSV(hue, 255, 255);
+ }
}
+
+
+#if (PARALLEL_OUTPUT_CHANNELS > 1)
+
+void multi_test() {
+ static bool debug = true;
+ const uint8_t step = (256 / PARALLEL_OUTPUT_CHANNELS);
+
+ if (debug) {
+ Serial.print("step: ");
+ Serial.println(step);
+ }
+
+ static_assert(PARALLEL_OUTPUT_CHANNELS <= 6, "");
+ for (uint8_t strip = 0; strip < PARALLEL_OUTPUT_CHANNELS; strip++) {
+ uint16_t pixelOffset;
+ uint16_t pixelCount;
+ if (strip == 0) {
+ pixelOffset = LedOffset<1>(); // uses one-based indices... sigh.
+ pixelCount = LedCount<1>(); // uses one-based indices... sigh.
+ }
+#if (PARALLEL_OUTPUT_CHANNELS >= 2)
+ else if (strip == 1) {
+ pixelOffset = LedOffset<2>(); // uses one-based indices... sigh.
+ pixelCount = LedCount<2>(); // uses one-based indices... sigh.
+ }
+#endif
+#if (PARALLEL_OUTPUT_CHANNELS >= 3)
+ else if (strip == 2) {
+ pixelOffset = LedOffset<3>(); // uses one-based indices... sigh.
+ pixelCount = LedCount<3>(); // uses one-based indices... sigh.
+ }
+#endif
+#if (PARALLEL_OUTPUT_CHANNELS >= 4)
+ else if (strip == 3) {
+ pixelOffset = LedOffset<4>(); // uses one-based indices... sigh.
+ pixelCount = LedCount<4>(); // uses one-based indices... sigh.
+ }
+#endif
+#if (PARALLEL_OUTPUT_CHANNELS > 5)
+ else if (strip == 4) {
+ pixelOffset = LedOffset<5>(); // uses one-based indices... sigh.
+ pixelCount = LedCount<5>(); // uses one-based indices... sigh.
+ }
+#endif
+#if (PARALLEL_OUTPUT_CHANNELS > 6)
+ else if (strip == 5) {
+ pixelOffset = LedOffset<6>(); // uses one-based indices... sigh.
+ pixelCount = LedCount<6>(); // uses one-based indices... sigh.
+ }
+#endif
+ else {
+ break;
+ }
+
+ uint8_t hue = gHue + strip * step;
+ CHSV c = CHSV(hue, 255, 255);
+
+ if (debug) {
+ Serial.print("hue: ");
+ Serial.println(hue);
+ }
+
+ for (uint16_t i = 0; i < pixelCount; i++) {
+ uint16_t j = i + pixelOffset;
+ leds[j] = c;
+
+ if (debug) {
+ Serial.print("j: ");
+ Serial.println(j);
+ }
+ }
+ }
+
+ debug = false;
+}
+#endif
+
diff --git a/esp8266-fastled-webserver/include/FSBrowser.hpp b/esp8266-fastled-webserver/include/FSBrowser.hpp
new file mode 100644
index 00000000..7fc021b1
--- /dev/null
+++ b/esp8266-fastled-webserver/include/FSBrowser.hpp
@@ -0,0 +1,18 @@
+#pragma once
+#if !defined(FS_BROWSER_HPP)
+#define FS_BROWSER_HPP
+
+
+//holds the current upload
+extern File fsUploadFile;
+
+//format bytes
+String formatBytes(size_t bytes);
+String getContentType(String filename);
+bool handleFileRead(String path);
+void handleFileUpload();
+void handleFileDelete();
+void handleFileCreate();
+void handleFileList();
+
+#endif
\ No newline at end of file
diff --git a/esp8266-fastled-webserver/include/Fields.hpp b/esp8266-fastled-webserver/include/Fields.hpp
new file mode 100644
index 00000000..e0e2ff8a
--- /dev/null
+++ b/esp8266-fastled-webserver/include/Fields.hpp
@@ -0,0 +1,33 @@
+/*
+ ESP8266 + FastLED + IR Remote: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) 2016 Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+#if !defined(FIELDS_HPP)
+#define FIELDS_HPP
+
+extern uint8_t power;
+extern uint8_t brightness;
+
+void setShowClock(uint8_t value);
+void setClockBackgroundFade(uint8_t value);
+
+String getFieldValue(String name);
+String setFieldValue(String name, String value);
+String getFieldsJson();
+
+
+#endif
diff --git a/esp8266-fastled-webserver/include/GradientPalettes.hpp b/esp8266-fastled-webserver/include/GradientPalettes.hpp
new file mode 100644
index 00000000..13afb31a
--- /dev/null
+++ b/esp8266-fastled-webserver/include/GradientPalettes.hpp
@@ -0,0 +1,39 @@
+#pragma once
+#if !defined(GRADIENT_PALETTES_HPP)
+#define GRADIENT_PALETTES_HPP
+
+DECLARE_GRADIENT_PALETTE( ib_jul01_gp );
+DECLARE_GRADIENT_PALETTE( es_vintage_57_gp );
+DECLARE_GRADIENT_PALETTE( es_vintage_01_gp );
+DECLARE_GRADIENT_PALETTE( es_rivendell_15_gp );
+DECLARE_GRADIENT_PALETTE( rgi_15_gp );
+DECLARE_GRADIENT_PALETTE( retro2_16_gp );
+DECLARE_GRADIENT_PALETTE( Analogous_1_gp );
+DECLARE_GRADIENT_PALETTE( es_pinksplash_08_gp );
+DECLARE_GRADIENT_PALETTE( es_pinksplash_07_gp );
+DECLARE_GRADIENT_PALETTE( Coral_reef_gp );
+DECLARE_GRADIENT_PALETTE( es_ocean_breeze_068_gp );
+DECLARE_GRADIENT_PALETTE( es_ocean_breeze_036_gp );
+DECLARE_GRADIENT_PALETTE( departure_gp );
+DECLARE_GRADIENT_PALETTE( es_landscape_64_gp );
+DECLARE_GRADIENT_PALETTE( es_landscape_33_gp );
+DECLARE_GRADIENT_PALETTE( rainbowsherbet_gp );
+DECLARE_GRADIENT_PALETTE( gr65_hult_gp );
+DECLARE_GRADIENT_PALETTE( gr64_hult_gp );
+DECLARE_GRADIENT_PALETTE( GMT_drywet_gp );
+DECLARE_GRADIENT_PALETTE( ib15_gp );
+DECLARE_GRADIENT_PALETTE( Fuschia_7_gp );
+DECLARE_GRADIENT_PALETTE( es_emerald_dragon_08_gp );
+DECLARE_GRADIENT_PALETTE( lava_gp );
+DECLARE_GRADIENT_PALETTE( fire_gp );
+DECLARE_GRADIENT_PALETTE( Colorfull_gp );
+DECLARE_GRADIENT_PALETTE( Magenta_Evening_gp );
+DECLARE_GRADIENT_PALETTE( Pink_Purple_gp );
+DECLARE_GRADIENT_PALETTE( Sunset_Real_gp );
+DECLARE_GRADIENT_PALETTE( es_autumn_19_gp );
+DECLARE_GRADIENT_PALETTE( BlacK_Blue_Magenta_White_gp );
+DECLARE_GRADIENT_PALETTE( BlacK_Magenta_Red_gp );
+DECLARE_GRADIENT_PALETTE( BlacK_Red_Magenta_Yellow_gp );
+DECLARE_GRADIENT_PALETTE( Blue_Cyan_Yellow_gp );
+
+#endif
diff --git a/esp8266-fastled-webserver/include/configs/controller/controller_esp32.h b/esp8266-fastled-webserver/include/configs/controller/controller_esp32.h
new file mode 100644
index 00000000..246ee964
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/controller/controller_esp32.h
@@ -0,0 +1,59 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#if !defined(ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP32_H)
+#define ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP32_H
+
+
+static_assert(PARALLEL_OUTPUT_CHANNELS <= 4, "ESP32 only has support for four parallel outputs defined, can be updated to support 16 outputs");
+
+// TODO: consider using I2S (instead of RMT) on the ESP32:
+//
+// #define FASTLED_ESP32_I2S true
+//
+// See https://github.com/FastLED/FastLED/issues/1220#issuecomment-822677011
+
+#define DATA_PIN
+
+#if !defined(DATA_PIN)
+ #if PARALLEL_OUTPUT_CHANNELS == 1
+ #define DATA_PIN 18 // d1 mini32 (same physical location as D5 on the d1 mini)
+ #else
+ #define DATA_PIN 23 // d1 mini32 (same physical location as D7 on the d1 mini)
+ #endif
+#endif
+
+#if !defined(DATA_PIN_2) && PARALLEL_OUTPUT_CHANNELS >= 2
+ #define DATA_PIN_2 19 // d1 mini32 (same physical location as D6 on the d1 mini)
+#endif
+#if !defined(DATA_PIN_3) && PARALLEL_OUTPUT_CHANNELS >= 3
+ #define DATA_PIN_3 5 // d1 mini32 (same physical location as D8 on the d1 mini)
+#endif
+#if !defined(DATA_PIN_4) && PARALLEL_OUTPUT_CHANNELS >= 4
+ #define DATA_PIN_4 18 // d1 mini32 (same physical location as D5 on the d1 mini)
+#endif
+
+
+
+#if defined(ENABLE_IR) && !defined(IR_RECV_PIN)
+ // Default pin for ESP32 is 16 (for d1 mini32, this is the same physical location as D4 on the d1 mini)
+ #define IR_RECV_PIN 16 // TODO: VERIFY THIS IS CORRECT VALUE
+#endif
+
+#endif // ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP32_H
diff --git a/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h b/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h
new file mode 100644
index 00000000..9ac16079
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h
@@ -0,0 +1,56 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#if !defined(ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP8266_H)
+#define ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP8266_H
+
+static_assert(PARALLEL_OUTPUT_CHANNELS <= 6, "ESP8266 only supports six parallel outputs");
+
+#if !defined(DATA_PIN)
+ #if PARALLEL_OUTPUT_CHANNELS == 1
+ #define DATA_PIN D5 // d1 mini
+ #else
+ #define DATA_PIN D7 // Fib512 uses different default for primary output pin
+ #endif
+#endif
+
+#if !defined(DATA_PIN_2) && PARALLEL_OUTPUT_CHANNELS >= 2
+ #define DATA_PIN_2 D6 // d1 mini
+#endif
+#if !defined(DATA_PIN_3) && PARALLEL_OUTPUT_CHANNELS >= 3
+ #define DATA_PIN_3 D8 // d1 mini
+#endif
+#if !defined(DATA_PIN_4) && PARALLEL_OUTPUT_CHANNELS >= 4
+ #define DATA_PIN_4 D5 // d1 mini
+#endif
+#if !defined(DATA_PIN_5) && PARALLEL_OUTPUT_CHANNELS >= 5
+ #define DATA_PIN_5 D1 // d1 mini
+#endif
+#if !defined(DATA_PIN_6) && PARALLEL_OUTPUT_CHANNELS >= 6
+ #define DATA_PIN_6 D2 // d1 mini
+#endif
+
+#if defined(ENABLE_IR) && !defined(IR_RECV_PIN)
+ #define IR_RECV_PIN D4
+#endif
+
+
+#define FASTLED_INTERRUPT_RETRY_COUNT 0
+
+#endif // ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP8266_H
diff --git a/esp8266-fastled-webserver/include/configs/controller/controller_template.h b/esp8266-fastled-webserver/include/configs/controller/controller_template.h
new file mode 100644
index 00000000..a658e2db
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/controller/controller_template.h
@@ -0,0 +1,45 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#if !defined(ESP8266_FASTLED_WEBSERVER_CONTROLLER_TEMPLATE_H)
+#define ESP8266_FASTLED_WEBSERVER_CONTROLLER_TEMPLATE_H
+
+// This header file describes the configuration for specific controllers
+// (e.g., ESP8266, ESP32, Adafruit QT Py, etc.)
+
+// The only MANDATORY setting is DATA_PIN.
+
+
+// The DATA_PIN defines the MCU's pin that is used to control the pixels
+#define DATA_PIN D5 // d1 mini
+// #define DATA_PIN 18 // d1 mini32 (same physical location as D5 on the d1 mini)
+
+// TODO: enable SPI-based chipsets based on whether CLOCK_PIN is defined?
+
+// FastLED configurations that may need to change, depending on the controller in use...
+// #define FASTLED_ALLOW_INTERRUPTS 1
+// #define INTERRUPT_THRESHOLD 1
+#define FASTLED_INTERRUPT_RETRY_COUNT 0
+
+// ENABLE_IR defines whether to include support for an IR receiver
+// #define ENABLE_IR
+// #define IR_RECV_PIN D4 // d1 mini
+// #define IR_RECV_PIN 16 // d1 mini32 (same physical location as D4 on the d1 mini)
+
+#endif // ESP8266_FASTLED_WEBSERVER_CONTROLLER_TEMPLATE_H
diff --git a/esp8266-fastled-webserver/include/configs/product/1628rings.h b/esp8266-fastled-webserver/include/configs/product/1628rings.h
new file mode 100644
index 00000000..af3b02d4
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/product/1628rings.h
@@ -0,0 +1,73 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#if !defined(ESP8266_FASTLED_WEBSERVER_PRODUCT_1628RINGS_H)
+#define ESP8266_FASTLED_WEBSERVER_PRODUCT_1628RINGS_H
+
+#if !defined(LED_TYPE)
+ #define LED_TYPE WS2812B
+#endif
+#if !defined(COLOR_ORDER)
+ #define COLOR_ORDER GRB
+#endif
+#if !defined(NUM_PIXELS)
+ #define NUM_PIXELS 1628
+#endif
+#if !defined(AVAILABLE_MILLI_AMPS)
+ #define AVAILABLE_MILLI_AMPS 2000 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
+#endif
+#if !defined(MAX_MILLI_AMPS_PER_PIXEL)
+ #define MAX_MILLI_AMPS_PER_PIXEL 60 // IMPORTANT: set to larger value if necessary
+#endif
+#if !defined(FRAMES_PER_SECOND)
+ #define FRAMES_PER_SECOND 1000 // No enforced delay?
+#endif
+#if !defined(DEFAULT_PATTERN_INDEX)
+ #define DEFAULT_PATTERN_INDEX 0
+#endif
+#if !defined(DEFAULT_BRIGHTNESS_INDEX)
+ #define DEFAULT_BRIGHTNESS_INDEX 0
+#endif
+#if !defined(DEFAULT_COLOR_CORRECTION)
+ #define DEFAULT_COLOR_CORRECTION UncorrectedColor // 1628-Rings did not specify; This is FastLED default
+#endif
+#if !defined(NAME_PREFIX)
+ #define NAME_PREFIX "ESP8266-"
+#endif
+#if !defined(PRODUCT_FRIENDLY_NAME)
+ #define PRODUCT_FRIENDLY_NAME "ESP8266 FastLED Webserver"
+#endif
+#if !defined(IS_FIBONACCI)
+ #define IS_FIBONACCI 0
+#endif
+#if !defined(HAS_COORDINATE_MAP)
+ #define HAS_COORDINATE_MAP 1
+#endif
+// TODO: combine HAS_POLAR_COORDS with HAS_COORDINATE_MAP
+#if !defined(HAS_POLAR_COORDS)
+ #define HAS_POLAR_COORDS 1
+#endif
+#if !defined(PARALLEL_OUTPUT_CHANNELS) // WARNING: Refresh rate for 1628 pixels over single output is ~15 frames / second MAXIMUM....
+ #define PARALLEL_OUTPUT_CHANNELS 1
+#endif
+
+
+
+
+#endif // ESP8266_FASTLED_WEBSERVER_PRODUCT_1628RINGS_H
diff --git a/esp8266-fastled-webserver/include/configs/product/default.h b/esp8266-fastled-webserver/include/configs/product/default.h
new file mode 100644
index 00000000..abef6778
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/product/default.h
@@ -0,0 +1,72 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#if !defined(ESP8266_FASTLED_WEBSERVER_PRODUCT_DEFAULT_H)
+#define ESP8266_FASTLED_WEBSERVER_PRODUCT_DEFAULT_H
+
+#if !defined(LED_TYPE)
+ #define LED_TYPE WS2811
+#endif
+#if !defined(COLOR_ORDER)
+ #define COLOR_ORDER RGB
+#endif
+#if !defined(NUM_PIXELS)
+ #define NUM_PIXELS 200
+#endif
+#if !defined(AVAILABLE_MILLI_AMPS)
+ #define AVAILABLE_MILLI_AMPS 2000 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
+#endif
+#if !defined(MAX_MILLI_AMPS_PER_PIXEL)
+ #define MAX_MILLI_AMPS_PER_PIXEL 60 // IMPORTANT: set to larger value if necessary
+#endif
+#if !defined(FRAMES_PER_SECOND)
+ #define FRAMES_PER_SECOND 120
+#endif
+#if !defined(DEFAULT_PATTERN_INDEX)
+ #define DEFAULT_PATTERN_INDEX 0
+#endif
+#if !defined(DEFAULT_BRIGHTNESS_INDEX)
+ #define DEFAULT_BRIGHTNESS_INDEX 3
+#endif
+#if !defined(DEFAULT_COLOR_CORRECTION)
+ #define DEFAULT_COLOR_CORRECTION TypicalLEDStrip
+#endif
+#if !defined(NAME_PREFIX)
+ #define NAME_PREFIX "ESP8266-"
+#endif
+#if !defined(PRODUCT_FRIENDLY_NAME)
+ #define PRODUCT_FRIENDLY_NAME "ESP8266 + FastLED"
+#endif
+#if !defined(IS_FIBONACCI)
+ #define IS_FIBONACCI 0
+#endif
+#if !defined(HAS_COORDINATE_MAP)
+ #define HAS_COORDINATE_MAP 0
+#endif
+#if !defined(HAS_POLAR_COORDS)
+ #define HAS_POLAR_COORDS 0
+#endif
+#if !defined(PARALLEL_OUTPUT_CHANNELS)
+ #define PARALLEL_OUTPUT_CHANNELS 1
+#endif
+
+
+
+
+#endif // ESP8266_FASTLED_WEBSERVER_PRODUCT_DEFAULT_H
diff --git a/esp8266-fastled-webserver/include/configs/product/esp8266_thing.h b/esp8266-fastled-webserver/include/configs/product/esp8266_thing.h
new file mode 100644
index 00000000..4b9399fe
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/product/esp8266_thing.h
@@ -0,0 +1,121 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#if !defined(ESP8266_FASTLED_WEBSERVER_PRODUCT_ESP8266_THING_H)
+#define ESP8266_FASTLED_WEBSERVER_PRODUCT_ESP8266_THING_H
+
+#if !defined(ARDUINO_ARCH_ESP8266)
+ #error "ESP8266 Thing currently only supports ESP8266"
+#endif
+
+
+#if !defined(LED_TYPE)
+ #define LED_TYPE WS2811
+#endif
+#if !defined(COLOR_ORDER)
+ #define COLOR_ORDER RGB
+#endif
+#if !defined(NUM_PIXELS)
+ #define NUM_PIXELS 300
+#endif
+#if !defined(AVAILABLE_MILLI_AMPS)
+ #define AVAILABLE_MILLI_AMPS 10000 // !!! 10Amps !!! Verify your power supply !!! IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
+#endif
+#if !defined(MAX_MILLI_AMPS_PER_PIXEL)
+ #define MAX_MILLI_AMPS_PER_PIXEL 60 // IMPORTANT: set to larger value if necessary
+#endif
+#if !defined(FRAMES_PER_SECOND)
+ #define FRAMES_PER_SECOND 120
+#endif
+#if !defined(DEFAULT_PATTERN_INDEX)
+ #define DEFAULT_PATTERN_INDEX 3
+#endif
+#if !defined(DEFAULT_BRIGHTNESS_INDEX)
+ #define DEFAULT_BRIGHTNESS_INDEX 0
+#endif
+#if !defined(DEFAULT_COLOR_CORRECTION)
+ #define DEFAULT_COLOR_CORRECTION TypicalLEDStrip
+#endif
+#if !defined(NAME_PREFIX)
+ #define NAME_PREFIX "ESP8266-"
+#endif
+#if !defined(PRODUCT_FRIENDLY_NAME)
+ #define PRODUCT_FRIENDLY_NAME "ESP8266 Thing"
+#endif
+#if !defined(IS_FIBONACCI)
+ #define IS_FIBONACCI 0
+#endif
+#if !defined(HAS_COORDINATE_MAP)
+ #define HAS_COORDINATE_MAP 0
+#endif
+#if !defined(HAS_POLAR_COORDS)
+ #define HAS_POLAR_COORDS 0
+#endif
+#if !defined(PARALLEL_OUTPUT_CHANNELS)
+ #define PARALLEL_OUTPUT_CHANNELS 6
+#endif
+#if !defined(PIXELS_ON_DATA_PIN_1)
+ #define PIXELS_ON_DATA_PIN_1 50
+#endif
+#if !defined(PIXELS_ON_DATA_PIN_2)
+ #define PIXELS_ON_DATA_PIN_2 50
+#endif
+#if !defined(PIXELS_ON_DATA_PIN_3)
+ #define PIXELS_ON_DATA_PIN_3 50
+#endif
+#if !defined(PIXELS_ON_DATA_PIN_4)
+ #define PIXELS_ON_DATA_PIN_4 50
+#endif
+#if !defined(PIXELS_ON_DATA_PIN_5)
+ #define PIXELS_ON_DATA_PIN_5 50
+#endif
+#if !defined(PIXELS_ON_DATA_PIN_6)
+ #define PIXELS_ON_DATA_PIN_6 50
+#endif
+
+#if defined(ARDUINO_ARCH_ESP8266)
+ // This board uses different data pins....
+ #if !defined(DATA_PIN)
+ #define DATA_PIN D1 // d1 mini
+ #endif
+ #if !defined(DATA_PIN_2) && PARALLEL_OUTPUT_CHANNELS >= 2
+ #define DATA_PIN_2 D2 // d1 mini
+ #endif
+ #if !defined(DATA_PIN_3) && PARALLEL_OUTPUT_CHANNELS >= 3
+ #define DATA_PIN_3 D5 // d1 mini
+ #endif
+ #if !defined(DATA_PIN_4) && PARALLEL_OUTPUT_CHANNELS >= 4
+ #define DATA_PIN_4 D6 // d1 mini
+ #endif
+ #if !defined(DATA_PIN_5) && PARALLEL_OUTPUT_CHANNELS >= 5
+ #define DATA_PIN_5 D7 // d1 mini
+ #endif
+ #if !defined(DATA_PIN_6) && PARALLEL_OUTPUT_CHANNELS >= 6
+ #define DATA_PIN_6 D8 // d1 mini
+ #endif
+#elif defined(ARDUINO_ARCH_ESP32)
+ #error "ESP8266 Thing currently only supports ESP8266"
+#else
+ #error "ESP8266 Thing currently only supports ESP8266"
+#endif
+
+
+
+
+#endif // ESP8266_FASTLED_WEBSERVER_PRODUCT_ESP8266_THING_H
diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci128.h b/esp8266-fastled-webserver/include/configs/product/fibonacci128.h
new file mode 100644
index 00000000..923f8c1a
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/product/fibonacci128.h
@@ -0,0 +1,70 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#if !defined(ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB128_H)
+#define ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB128_H
+
+#if !defined(LED_TYPE)
+ #define LED_TYPE WS2812B
+#endif
+#if !defined(COLOR_ORDER)
+ #define COLOR_ORDER GRB
+#endif
+#if !defined(NUM_PIXELS)
+ #define NUM_PIXELS 128
+#endif
+#if !defined(AVAILABLE_MILLI_AMPS)
+ #define AVAILABLE_MILLI_AMPS 1400 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
+#endif
+#if !defined(MAX_MILLI_AMPS_PER_PIXEL)
+ #define MAX_MILLI_AMPS_PER_PIXEL 60 // IMPORTANT: set to larger value if necessary
+#endif
+#if !defined(FRAMES_PER_SECOND)
+ #define FRAMES_PER_SECOND 120
+#endif
+#if !defined(DEFAULT_PATTERN_INDEX)
+ #define DEFAULT_PATTERN_INDEX 3
+#endif
+#if !defined(DEFAULT_BRIGHTNESS_INDEX)
+ #define DEFAULT_BRIGHTNESS_INDEX 2
+#endif
+#if !defined(DEFAULT_COLOR_CORRECTION)
+ #define DEFAULT_COLOR_CORRECTION TypicalSMD5050
+#endif
+#if !defined(NAME_PREFIX)
+ #define NAME_PREFIX "Fibonacci128-"
+#endif
+#if !defined(PRODUCT_FRIENDLY_NAME)
+ #define PRODUCT_FRIENDLY_NAME "Fibonacci128"
+#endif
+#if !defined(IS_FIBONACCI)
+ #define IS_FIBONACCI 1
+#endif
+#if !defined(HAS_COORDINATE_MAP)
+ #define HAS_COORDINATE_MAP 1
+#endif
+#if !defined(HAS_POLAR_COORDS)
+ #define HAS_POLAR_COORDS 0
+#endif
+#if !defined(PARALLEL_OUTPUT_CHANNELS)
+ #define PARALLEL_OUTPUT_CHANNELS 1
+#endif
+
+
+#endif // ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB128_H
diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci256.h b/esp8266-fastled-webserver/include/configs/product/fibonacci256.h
new file mode 100644
index 00000000..488dc8b2
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/product/fibonacci256.h
@@ -0,0 +1,72 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#if !defined(ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB256_H)
+#define ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB256_H
+
+#if !defined(LED_TYPE)
+ #define LED_TYPE WS2812B
+#endif
+#if !defined(COLOR_ORDER)
+ #define COLOR_ORDER GRB
+#endif
+#if !defined(NUM_PIXELS)
+ #define NUM_PIXELS 256
+#endif
+#if !defined(AVAILABLE_MILLI_AMPS)
+ #define AVAILABLE_MILLI_AMPS 1600 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
+#endif
+#if !defined(MAX_MILLI_AMPS_PER_PIXEL)
+ #define MAX_MILLI_AMPS_PER_PIXEL 12 // IMPORTANT: set to larger value if necessary
+#endif
+#if !defined(FRAMES_PER_SECOND)
+ #define FRAMES_PER_SECOND 120
+#endif
+#if !defined(DEFAULT_PATTERN_INDEX)
+ #define DEFAULT_PATTERN_INDEX 3
+#endif
+#if !defined(DEFAULT_BRIGHTNESS_INDEX)
+ #define DEFAULT_BRIGHTNESS_INDEX 3
+#endif
+#if !defined(DEFAULT_COLOR_CORRECTION)
+ #define DEFAULT_COLOR_CORRECTION TypicalSMD5050
+#endif
+#if !defined(NAME_PREFIX)
+ #define NAME_PREFIX "Fibonacci256-"
+#endif
+#if !defined(PRODUCT_FRIENDLY_NAME)
+ #define PRODUCT_FRIENDLY_NAME "Fibonacci256"
+#endif
+#if !defined(IS_FIBONACCI)
+ #define IS_FIBONACCI 1
+#endif
+#if !defined(HAS_COORDINATE_MAP)
+ #define HAS_COORDINATE_MAP 1
+#endif
+#if !defined(HAS_POLAR_COORDS)
+ #define HAS_POLAR_COORDS 0
+#endif
+#if !defined(PARALLEL_OUTPUT_CHANNELS)
+ #define PARALLEL_OUTPUT_CHANNELS 1
+#endif
+
+
+
+
+#endif // ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB256_H
diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci32.h b/esp8266-fastled-webserver/include/configs/product/fibonacci32.h
new file mode 100644
index 00000000..d3415998
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/product/fibonacci32.h
@@ -0,0 +1,70 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#if !defined(ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB32_H)
+#define ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB32_H
+
+#if !defined(LED_TYPE)
+ #define LED_TYPE WS2812B
+#endif
+#if !defined(COLOR_ORDER)
+ #define COLOR_ORDER GRB
+#endif
+#if !defined(NUM_PIXELS)
+ #define NUM_PIXELS 34 // !!! Two free pixels! :)
+#endif
+#if !defined(AVAILABLE_MILLI_AMPS)
+ #define AVAILABLE_MILLI_AMPS 2000 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
+#endif
+#if !defined(MAX_MILLI_AMPS_PER_PIXEL)
+ #define MAX_MILLI_AMPS_PER_PIXEL 60 // IMPORTANT: set to larger value if necessary
+#endif
+#if !defined(FRAMES_PER_SECOND)
+ #define FRAMES_PER_SECOND 120
+#endif
+#if !defined(DEFAULT_PATTERN_INDEX)
+ #define DEFAULT_PATTERN_INDEX 0
+#endif
+#if !defined(DEFAULT_BRIGHTNESS_INDEX)
+ #define DEFAULT_BRIGHTNESS_INDEX 0 // very low brightness by default for this board!
+#endif
+#if !defined(DEFAULT_COLOR_CORRECTION)
+ #define DEFAULT_COLOR_CORRECTION TypicalSMD5050
+#endif
+#if !defined(NAME_PREFIX)
+ #define NAME_PREFIX "Fibonacci32-"
+#endif
+#if !defined(PRODUCT_FRIENDLY_NAME)
+ #define PRODUCT_FRIENDLY_NAME "Fibonacci32"
+#endif
+#if !defined(IS_FIBONACCI)
+ #define IS_FIBONACCI 1
+#endif
+#if !defined(HAS_COORDINATE_MAP)
+ #define HAS_COORDINATE_MAP 1
+#endif
+#if !defined(HAS_POLAR_COORDS)
+ #define HAS_POLAR_COORDS 0
+#endif
+#if !defined(PARALLEL_OUTPUT_CHANNELS)
+ #define PARALLEL_OUTPUT_CHANNELS 1
+#endif
+
+
+#endif // ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB32_H
diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci512.h b/esp8266-fastled-webserver/include/configs/product/fibonacci512.h
new file mode 100644
index 00000000..e72f204b
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/product/fibonacci512.h
@@ -0,0 +1,82 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#if !defined(ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB512_MINI_H)
+#define ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB512_MINI_H
+
+#if !defined(LED_TYPE)
+ #define LED_TYPE WS2812B
+#endif
+#if !defined(COLOR_ORDER)
+ #define COLOR_ORDER GRB
+#endif
+#if !defined(NUM_PIXELS)
+ #define NUM_PIXELS 512
+#endif
+#if !defined(AVAILABLE_MILLI_AMPS)
+ #define AVAILABLE_MILLI_AMPS 2000 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
+#endif
+#if !defined(MAX_MILLI_AMPS_PER_PIXEL)
+ #define MAX_MILLI_AMPS_PER_PIXEL 48 // IMPORTANT: set to larger value if necessary
+#endif
+#if !defined(FRAMES_PER_SECOND)
+ #define FRAMES_PER_SECOND 120
+#endif
+#if !defined(DEFAULT_PATTERN_INDEX)
+ #define DEFAULT_PATTERN_INDEX 3
+#endif
+#if !defined(DEFAULT_BRIGHTNESS_INDEX)
+ #define DEFAULT_BRIGHTNESS_INDEX 3
+#endif
+#if !defined(DEFAULT_COLOR_CORRECTION)
+ #define DEFAULT_COLOR_CORRECTION TypicalSMD5050
+#endif
+#if !defined(NAME_PREFIX)
+ #define NAME_PREFIX "Fibonacci512-"
+#endif
+#if !defined(PRODUCT_FRIENDLY_NAME)
+ #define PRODUCT_FRIENDLY_NAME "Fibonacci512"
+#endif
+#if !defined(IS_FIBONACCI)
+ #define IS_FIBONACCI 1
+#endif
+#if !defined(HAS_COORDINATE_MAP)
+ #define HAS_COORDINATE_MAP 1
+#endif
+#if !defined(HAS_POLAR_COORDS)
+ #define HAS_POLAR_COORDS 0
+#endif
+#if !defined(PARALLEL_OUTPUT_CHANNELS)
+ #define PARALLEL_OUTPUT_CHANNELS 4
+#endif
+#if !defined(PIXELS_ON_DATA_PIN_1)
+ #define PIXELS_ON_DATA_PIN_1 121
+#endif
+#if !defined(PIXELS_ON_DATA_PIN_2)
+ #define PIXELS_ON_DATA_PIN_2 120
+#endif
+#if !defined(PIXELS_ON_DATA_PIN_3)
+ #define PIXELS_ON_DATA_PIN_3 121
+#endif
+#if !defined(PIXELS_ON_DATA_PIN_4)
+ #define PIXELS_ON_DATA_PIN_4 150
+#endif
+
+
+#endif // ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB512_MINI_H
diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci64.h b/esp8266-fastled-webserver/include/configs/product/fibonacci64.h
new file mode 100644
index 00000000..89dd1715
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/product/fibonacci64.h
@@ -0,0 +1,117 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#if !defined(ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB64_H)
+#define ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB64_H
+
+// FIBONACCI64 comes in multiple variants:
+// Full (86mm) ==> ESP8266, WS2812B-5050 == ~60mA / pixel, no touch support built-in
+// https://www.tindie.com/products/jasoncoon/fibonacci64-86mm-disc-with-64-ws2812b-rgb-leds/
+//
+// Mini (64mm) ==> ESP8266, WS2812B-3535 == ~??mA / pixel, no touch support built-in
+// https://www.tindie.com/products/jasoncoon/fibonacci64-mini-64mm-disc-with-64-rgb-leds/
+//
+
+// TODO: Enable Micro and Nano, which have no WiFi and use SAMD21E...
+// Micro (40mm) ==> QT Py, WS2812C-2020 == ~5mA / pixel
+// Nano (33mm) ==> QT Py, SK6805-EC15 == ~5mA / pixel
+//
+// https://www.tindie.com/products/jasoncoon/fibonacci64-micro-40mm-disc-with-64-rgb-leds/
+// https://github.com/jasoncoon/fibonacci64-touch-demo
+//
+// https://www.tindie.com/products/jasoncoon/fibonacci64-nano-33mm-disc-with-64-rgb-leds/
+// https://github.com/jasoncoon/fibonacci64-nano-touch-demo
+//
+// NOTE: code sets to use WS2812B timings, even on Nano (SK6805 timings differ from WS2812B)
+// NOTE: QT Py data pin A10, brightness 32
+// NOTE: QT Py touch pins:
+// Micro: A0, A1, A2, A3
+// Nano: A0, A1, A2
+//
+
+#if defined(PRODUCT_FIBONACCI64_MICRO) || defined(PRODUCT_FIBONACCI64_NANO)
+ #error "The Fibonacci64 micro and nano are not yet supported."
+#endif
+
+#if !defined(LED_TYPE)
+ #if defined(PRODUCT_FIBONACCI64_NANO)
+ #define LED_TYPE SK6812
+ #else
+ #define LED_TYPE WS2812B
+ #endif
+#endif
+#if !defined(COLOR_ORDER)
+ #define COLOR_ORDER GRB
+#endif
+#if !defined(NUM_PIXELS)
+ #define NUM_PIXELS 64
+#endif
+#if !defined(AVAILABLE_MILLI_AMPS)
+ #define AVAILABLE_MILLI_AMPS 1400 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
+#endif
+#if !defined(MAX_MILLI_AMPS_PER_PIXEL)
+ #if defined(PRODUCT_FIBONACCI64_MICRO) || defined(PRODUCT_FIBONACCI64_NANO)
+ #define MAX_MILLI_AMPS_PER_PIXEL 5 // IMPORTANT: set to larger value if necessary
+ #else
+ #define MAX_MILLI_AMPS_PER_PIXEL 60 // IMPORTANT: set to larger value if necessary
+ #endif
+#endif
+#if !defined(FRAMES_PER_SECOND)
+ #define FRAMES_PER_SECOND 120
+#endif
+#if !defined(DEFAULT_PATTERN_INDEX)
+ #define DEFAULT_PATTERN_INDEX 3
+#endif
+#if !defined(DEFAULT_BRIGHTNESS_INDEX)
+ #define DEFAULT_BRIGHTNESS_INDEX 3
+#endif
+#if !defined(DEFAULT_COLOR_CORRECTION)
+ #define DEFAULT_COLOR_CORRECTION TypicalSMD5050
+#endif
+#if !defined(NAME_PREFIX)
+ #define NAME_PREFIX "Fibonacci64-"
+#endif
+#if !defined(PRODUCT_FRIENDLY_NAME)
+
+ #if defined(PRODUCT_FIBONACCI64_FULL)
+ #define PRODUCT_FRIENDLY_NAME "Fibonacci64"
+ #elif defined(PRODUCT_FIBONACCI64_MINI)
+ #define PRODUCT_FRIENDLY_NAME "Fibonacci64 Mini"
+ #elif defined(PRODUCT_FIBONACCI64_MICRO)
+ #define PRODUCT_FRIENDLY_NAME "Fibonacci64 Micro"
+ #elif defined(PRODUCT_FIBONACCI64_NANO)
+ #define PRODUCT_FRIENDLY_NAME "Fibonacci64 Nano"
+ #endif
+
+#endif
+#if !defined(IS_FIBONACCI)
+ #define IS_FIBONACCI 1
+#endif
+#if !defined(HAS_COORDINATE_MAP)
+ #define HAS_COORDINATE_MAP 1
+#endif
+#if !defined(HAS_POLAR_COORDS)
+ #define HAS_POLAR_COORDS 0
+#endif
+#if !defined(PARALLEL_OUTPUT_CHANNELS)
+ #define PARALLEL_OUTPUT_CHANNELS 1
+#endif
+
+
+#endif // ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB64_H
diff --git a/esp8266-fastled-webserver/include/configs/product/kraken64.h b/esp8266-fastled-webserver/include/configs/product/kraken64.h
new file mode 100644
index 00000000..9a3d9b20
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/product/kraken64.h
@@ -0,0 +1,95 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#if !defined(ESP8266_FASTLED_WEBSERVER_PRODUCT_KRAKEN64_H)
+#define ESP8266_FASTLED_WEBSERVER_PRODUCT_KRAKEN64_H
+
+// FIBONACCI64 comes in multiple variants:
+// Full (86mm) ==> ESP8266, WS2812B-5050 == ~60mA / pixel, no touch support built-in
+// https://www.tindie.com/products/jasoncoon/fibonacci64-86mm-disc-with-64-ws2812b-rgb-leds/
+//
+// Mini (64mm) ==> ESP8266, WS2812B-3535 == ~??mA / pixel, no touch support built-in
+// https://www.tindie.com/products/jasoncoon/fibonacci64-mini-64mm-disc-with-64-rgb-leds/
+//
+
+// TODO: Enable Micro and Nano, which have no WiFi and use SAMD21E...
+// Micro (40mm) ==> QT Py, WS2812C-2020 == ~5mA / pixel
+// Nano (33mm) ==> QT Py, SK6805-EC15 == ~5mA / pixel
+//
+// https://www.tindie.com/products/jasoncoon/fibonacci64-micro-40mm-disc-with-64-rgb-leds/
+// https://github.com/jasoncoon/fibonacci64-touch-demo
+//
+// https://www.tindie.com/products/jasoncoon/fibonacci64-nano-33mm-disc-with-64-rgb-leds/
+// https://github.com/jasoncoon/fibonacci64-nano-touch-demo
+//
+// NOTE: code sets to use WS2812B timings, even on Nano (SK6805 timings differ from WS2812B)
+// NOTE: QT Py data pin A10, brightness 32
+// NOTE: QT Py touch pins:
+// Micro: A0, A1, A2, A3
+// Nano: A0, A1, A2
+//
+
+#if !defined(LED_TYPE)
+ #define LED_TYPE WS2812B
+#endif
+#if !defined(COLOR_ORDER)
+ #define COLOR_ORDER GRB
+#endif
+#if !defined(NUM_PIXELS)
+ #define NUM_PIXELS 64
+#endif
+#if !defined(AVAILABLE_MILLI_AMPS)
+ #define AVAILABLE_MILLI_AMPS 1400 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
+#endif
+#if !defined(MAX_MILLI_AMPS_PER_PIXEL)
+ #define MAX_MILLI_AMPS_PER_PIXEL 60 // IMPORTANT: set to larger value if necessary
+#endif
+#if !defined(FRAMES_PER_SECOND)
+ #define FRAMES_PER_SECOND 120
+#endif
+#if !defined(DEFAULT_PATTERN_INDEX)
+ #define DEFAULT_PATTERN_INDEX 0
+#endif
+#if !defined(DEFAULT_BRIGHTNESS_INDEX)
+ #define DEFAULT_BRIGHTNESS_INDEX 3
+#endif
+#if !defined(DEFAULT_COLOR_CORRECTION)
+ #define DEFAULT_COLOR_CORRECTION TypicalSMD5050
+#endif
+#if !defined(NAME_PREFIX)
+ #define NAME_PREFIX "Kraken64-"
+#endif
+#if !defined(PRODUCT_FRIENDLY_NAME)
+ #define PRODUCT_FRIENDLY_NAME "Kraken64"
+#endif
+#if !defined(IS_FIBONACCI)
+ #define IS_FIBONACCI 0
+#endif
+#if !defined(HAS_COORDINATE_MAP)
+ #define HAS_COORDINATE_MAP 1
+#endif
+#if !defined(HAS_POLAR_COORDS)
+ #define HAS_POLAR_COORDS 0
+#endif
+#if !defined(PARALLEL_OUTPUT_CHANNELS)
+ #define PARALLEL_OUTPUT_CHANNELS 1
+#endif
+
+
+#endif // ESP8266_FASTLED_WEBSERVER_PRODUCT_KRAKEN64_H
diff --git a/esp8266-fastled-webserver/include/configs/product/product_template.h b/esp8266-fastled-webserver/include/configs/product/product_template.h
new file mode 100644
index 00000000..7ea04679
--- /dev/null
+++ b/esp8266-fastled-webserver/include/configs/product/product_template.h
@@ -0,0 +1,174 @@
+/*
+ ESP8266 FastLED WebServer: https://github.com/jasoncoon/esp8266-fastled-webserver
+ Copyright (C) Jason Coon
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+*/
+#pragma once
+
+#error #if !defined(ESP8266_FASTLED_WEBSERVER_PRODUCT_xyzzy_H)
+#error #define ESP8266_FASTLED_WEBSERVER_PRODUCT_xyzzy_H
+
+// This template documents the settings to configure a specific "product"
+// for building from this repository.
+
+// The following are MANDATORY ... they must be defined to appropriate values
+// This template provides the default values as used by the prior main branch
+
+// LED_TYPE defines the control pattern for the LEDs
+// See https://github.com/FastLED/FastLED/blob/b5874b588ade1d2639925e4e9719fa7d3c9d9e94/src/FastLED.h#L92-L119
+
+#if !defined(LED_TYPE)
+ #define LED_TYPE WS2811
+#endif
+
+// COLOR_ORDER defines the order that each pixel expects the data to arrive in
+// See https://github.com/FastLED/FastLED/blob/765d4244889a692bb453cd4087af31e01c937035/src/pixeltypes.h#L852-L859
+#if !defined(COLOR_ORDER)
+ #define COLOR_ORDER RGB
+#endif
+
+// NUM_PIXELS is the total number of pixels to be generated / output
+#if !defined(NUM_PIXELS)
+ #define NUM_PIXELS 200
+#endif
+// AVAILABLE_MILLI_AMPS is based on the power supply. Recommended to use no more than 80% of actual rated maximum.
+#if !defined(AVAILABLE_MILLI_AMPS)
+ #error #define AVAILABLE_MILLI_AMPS x2000x // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA)
+#endif
+
+// MAX_MILLI_AMPS_PER_PIXEL is used by FastLED to reduce change of exceeding total available milliamps.
+#if !defined(MAX_MILLI_AMPS_PER_PIXEL)
+ #define MAX_MILLI_AMPS_PER_PIXEL 60 // IMPORTANT: set to larger value if necessary
+#endif
+
+// FRAMES_PER_SECOND is a frame LIMIT per second. This is approximate.
+#if !defined(FRAMES_PER_SECOND)
+ #define FRAMES_PER_SECOND 120
+#endif
+
+// DEFAULT_PATTERN_INDEX allows different products to default to different patterns
+#if !defined(DEFAULT_PATTERN_INDEX)
+ #define DEFAULT_PATTERN_INDEX 0
+#endif
+
+// DEFAULT_BRIGHTNESS_INDEX allows different products to default to different brightness (e.g., from brightness[5] array)
+#if !defined(DEFAULT_BRIGHTNESS_INDEX)
+ #define DEFAULT_BRIGHTNESS_INDEX 3
+#endif
+
+// DEFAULT_COLOR_CORRECTION defines which FastLED built-in color correction to apply
+// Options include:
+// TypicalSMD5050 // 0xFFB0F0 == 255, 176, 240
+// TypicalLEDStrip // 0xFFB0F0 == 255, 176, 240
+// Typical8mmPixel // 0xFFE08C == 255, 224, 140
+// TypicalPixelString // 0xFFE08C == 255, 224, 140
+// UncorrectedColor // 0xFFFFFF == 255, 255, 255
+//
+// Likely that you can encode any RGB value:
+// static_cast(0xRRGGBB)
+//
+// See https://github.com/FastLED/FastLED/blob/b5874b588ade1d2639925e4e9719fa7d3c9d9e94/src/color.h#L13-L32
+#if !defined(DEFAULT_COLOR_CORRECTION)
+ #define DEFAULT_COLOR_CORRECTION TypicalLEDStrip
+#endif
+
+
+// NAME_PREFIX defines the product-specific prefix for auto-generated hostname
+#if !defined(NAME_PREFIX)
+ #define NAME_PREFIX "ESP8266-"
+#endif
+
+// PRODUCT_FRIENDLY_NAME is used in HTML page's title and navigation bar
+// It is modified when js/app.js loads, by parsing json data generated from device
+#if !defined(PRODUCT_FRIENDLY_NAME)
+ #define PRODUCT_FRIENDLY_NAME "ESP8266 + FastLED"
+#endif
+
+// IS_FIBONACCI is true when there are pre-defined mappings from physical pixel
+// indices to Vogel order (which is also order of increasing radius),
+// and the inverse mapping from Vogel order back to physical pixel index.
+// IS_FIBONACCI also implies HAS_COORDINATE_MAP.
+//
+// When this is true, the following must be defined in map.h:
+//
+// const uint8_t physicalToFibonacci[NUM_PIXELS];
+// const uint8_t fibonacciToPhysical[NUM_PIXELS];
+//
+// NOTE: physicalToFibonacci[] and fibonacciToPhysical[] are uint16_t when
+// NUM_PIXELS is greater than 256.
+#if !defined(IS_FIBONACCI)
+ #define IS_FIBONACCI 1
+#endif
+
+// HAS_COORDINATE_MAP is true when there are mappings to define
+// both the X,Y coordinates and the angles for each pixel.
+//
+// When this is true, the following must be defined in map.h:
+//
+// const uint8_t coordsX[NUM_PIXELS];
+// const uint8_t coordsY[NUM_PIXELS];
+// const uint8_t angles[NUM_PIXELS];
+#if !defined(HAS_COORDINATE_MAP)
+ #define HAS_COORDINATE_MAP 1
+#endif
+
+// HAS_POLAR_COORDS is true when there are mappings to define
+// ... TODO: add definition for polar coordinates define ...
+#if !defined(HAS_POLAR_COORDS)
+ #define HAS_POLAR_COORDS 0
+#endif
+
+
+// PARALLEL_OUTPUT_CHANNELS indicates the number of independent channels
+// that should be configured. When this value == 1, DATA_PIN is used to
+// control all pixels.
+//
+// When this value >= 2, this file must define:
+//
+// #define PIXELS_ON_DATA_PIN_1 wc
+// #define PIXELS_ON_DATA_PIN_2 xc
+// #define PIXELS_ON_DATA_PIN_3 yc
+// ...
+// #define PIXELS_ON_DATA_PIN_n zc
+//
+// *AND* the controller must support the required number of channels.
+//
+// The controller header file will define default values for the data pins,
+// by defining the following symbols:
+//
+// #define DATA_PIN w
+// #define DATA_PIN_2 x
+// #define DATA_PIN_3 y
+// ...
+// #define DATA_PIN_n z
+//
+// These can be overridden from the board-default values by defining these
+// values in the product header template.
+//
+// See Fibonacci512 and ESPTHING as examples of multi-channel outputs.
+//
+#if !defined(PARALLEL_OUTPUT_CHANNELS)
+ #define PARALLEL_OUTPUT_CHANNELS 1
+#endif
+
+// // By default, no IR support is included. Define ENABLE_IR to enable IR support.
+// #define ENABLE_IR
+// // When ENABLE_IR is defined, can also override controller-specific default:
+// // #define IR_RECV_PIN D99
+
+
+
+
+#error #endif // ESP8266_FASTLED_WEBSERVER_PRODUCT_xyzz_H
diff --git a/esp8266-fastled-webserver/include/simplehacks/array_size2.h b/esp8266-fastled-webserver/include/simplehacks/array_size2.h
new file mode 100644
index 00000000..fdf87e11
--- /dev/null
+++ b/esp8266-fastled-webserver/include/simplehacks/array_size2.h
@@ -0,0 +1,147 @@
+/**
+
+The MIT License (MIT)
+
+Copyright (c) SimpleHacks, Henry Gabryjelski
+https://github.com/SimpleHacks/UtilHeaders
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+*/
+
+#ifndef ARRAYSIZE2_H
+#define ARRAYSIZE2_H
+
+/**
+ The following, if defined prior to inclusion of this header file,
+ will modify its behavior as noted:
+
+ ARRAYSIZE2_SHOW_VERSION_MESSAGE
+ -- if defined, will show which version of ARRAY_SIZE2 macro is selected
+ */
+
+
+// see example source at:
+// [https://godbolt.org/z/FKilKo]
+#ifndef __has_feature
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+#endif
+
+#if __cplusplus >= 201103L || /* any compiler claiming C++11 support */ \
+ (_MSC_VER >= 1900 && __cplusplus != 199711L) || /* Visual C++ 2015 or higher */ \
+ __has_feature(cxx_constexpr) /* CLang versions supporting constexp */
+
+ #include // required for size_t
+ #if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
+ #pragma message( "ARRAY_SIZE2 -- Using C++11 version" )
+ #endif
+
+ namespace detail
+ {
+ template
+ constexpr size_t ARRAY_SIZE2_ARGUMENT_CANNOT_BE_POINTER(T const (&)[N]) noexcept
+ {
+ return N;
+ }
+ } // namespace detail
+ #define ARRAY_SIZE2(arr) detail::ARRAY_SIZE2_ARGUMENT_CANNOT_BE_POINTER(arr)
+
+#elif __cplusplus >= 199711L && ( /* C++ 98 trick */ \
+ defined(__INTEL_COMPILER) || \
+ defined(__clang__) || \
+ (defined(__GNUC__) && ( \
+ (__GNUC__ > 4) || \
+ (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) \
+ )))
+
+ #include // required for size_t
+ #if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
+ #pragma message "ARRAY_SIZE2 -- Using C++98 version"
+ #endif
+ template
+ char(&_ArraySizeHelperRequiresArray(T(&)[N]))[N];
+ #define ARRAY_SIZE2(x) sizeof(_ArraySizeHelperRequiresArray(x))
+
+#elif defined(__cplusplus) // && ((__cplusplus >= 199711L) || defined(__INTEL_COMPILER) || defined(__clang__))
+
+ #if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
+ #pragma message( "ARRAY_SIZE2 -- Using Ivan J. Johnson's C++ version" )
+ #endif
+ /*
+ Works on older compilers, even Visual C++ 6....
+ Created by Ivan J. Johnson, March 06, 2007
+ See http://drdobbs.com/cpp/197800525?pgno=1
+
+ Full description is in markdown file array_size2.md
+ */
+ #define ARRAY_SIZE2(arr) ( \
+ 0 * sizeof(reinterpret_cast(arr)) + /*check1*/ \
+ 0 * sizeof(::Bad_arg_to_ARRAY_SIZE2::check_type((arr), &(arr))) + /*check2*/ \
+ sizeof(arr) / sizeof((arr)[0]) /* eval */ \
+ )
+
+ struct Bad_arg_to_ARRAY_SIZE2 {
+ class Is_pointer; // incomplete
+ class Is_array {};
+ template
+ static Is_pointer check_type(T const *, T const * const *);
+ static Is_array check_type(void const *, void const *);
+ };
+
+#elif !defined(__cplusplus) && defined(__GNUC__)
+
+ // Even C can have type-safety for equivalent of ARRAY_SIZE() macro,
+ // when using the following two GCC extensions:
+ // typeof()
+ // __builtin_types_compatible_p()
+
+ #if defined(ARRAYSIZE2_SHOW_VERSION_MESSAGE)
+ #pragma message( "ARRAY_SIZE2 -- Using GNUC version" )
+ #endif
+
+ // validated using:
+ // MSP430 gcc 4.5.3
+ // x86-64 icc 16.0.3
+ // x86-64 gcc 4.1.2
+ // x86-64 clang 3.0.0
+ // AVR gcc 4.5.4
+ // ARM gcc 4.5.4
+
+ #define __SIMPLEHACKS_COMPATIBLE_TYPES__(a,b) __builtin_types_compatible_p(typeof(a), typeof(b)) // GCC extensions
+ #define __SIMPLEHACKS_BUILD_ERROR_ON_NONZERO__(x) (sizeof(struct { int:-!!(x)*0x1ee7;})) // if x is zero, reports "error: negative width in bit-field ''"
+ #define __SIMPLEHACKS_MUST_BE_ARRAY__(x) __SIMPLEHACKS_BUILD_ERROR_ON_NONZERO__(__SIMPLEHACKS_COMPATIBLE_TYPES__((x), &(*x)))
+ #define ARRAY_SIZE2(_arr) ( (sizeof(_arr) / sizeof((_arr)[0])) + __SIMPLEHACKS_MUST_BE_ARRAY__(_arr) ) // compile-time error if not an array
+
+#else
+
+ // The good news is that all compilers (as of 20202-05-08)
+ // on godbolt.org are fully supported. Therefore, if some
+ // other compiler does not support any of the above method,
+ // it's important to force a compile-time error, to avoid
+ // any suggestion that this provides a safe macro.
+
+ #error "Unable to provide type-safe ARRAY_SIZE2 macro"
+
+
+#endif
+
+
+#endif // ARRAYSIZE2_H
diff --git a/esp8266-fastled-webserver/include/simplehacks/compile_date.h b/esp8266-fastled-webserver/include/simplehacks/compile_date.h
new file mode 100644
index 00000000..efac7fd9
--- /dev/null
+++ b/esp8266-fastled-webserver/include/simplehacks/compile_date.h
@@ -0,0 +1,136 @@
+/**
+
+The MIT License (MIT)
+
+Copyright (c) SimpleHacks, Henry Gabryjelski
+https://github.com/SimpleHacks/UtilHeaders
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+*/
+
+#ifndef COMPILE_DATE_H
+#define COMPILE_DATE_H
+
+// see https://godbolt.org/z/3dSuqQ
+
+#ifndef __has_feature
+ #define __has_feature(x) 0 // Compatibility with non-clang compilers.
+#endif
+
+// This allows conditional declaration of the below as `constexpr`,
+// unless the compiler has not implemented the relevant feature.
+#if __cpp_constexpr >= 200704 || __has_feature(cxx_constexpr) // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf
+ #define __COMPILE_DATE_H_CONSTEXPR constexpr
+#else
+ #define __COMPILE_DATE_H_CONSTEXPR
+#endif
+
+#define __DATE_YEAR_INT__ ((( \
+ (__DATE__ [ 7u] - '0') * 10u + \
+ (__DATE__ [ 8u] - '0')) * 10u + \
+ (__DATE__ [ 9u] - '0')) * 10u + \
+ (__DATE__ [10u] - '0'))
+
+#define __DATE_MONTH_INT__ ( \
+ (__DATE__ [2u] == 'n' && __DATE__ [1u] == 'a') ? 1u /*Jan*/ \
+: (__DATE__ [2u] == 'b' ) ? 2u /*Feb*/ \
+: (__DATE__ [2u] == 'r' && __DATE__ [1u] == 'a') ? 3u /*Mar*/ \
+: (__DATE__ [2u] == 'r' ) ? 4u /*Apr*/ \
+: (__DATE__ [2u] == 'y' ) ? 5u /*May*/ \
+: (__DATE__ [2u] == 'n' ) ? 6u /*Jun*/ \
+: (__DATE__ [2u] == 'l' ) ? 7u /*Jul*/ \
+: (__DATE__ [2u] == 'g' ) ? 8u /*Aug*/ \
+: (__DATE__ [2u] == 'p' ) ? 9u /*Sep*/ \
+: (__DATE__ [2u] == 't' ) ? 10u /*Oct*/ \
+: (__DATE__ [2u] == 'v' ) ? 11u /*Nov*/ \
+: 12u /*Dec*/ )
+
+#define __DATE_DAY_INT__ ( \
+ (__DATE__ [4u] == ' ' ? 0u : __DATE__ [4u] - '0') * 10u \
+ + (__DATE__ [5u] - '0') )
+
+// __TIME__ expands to an eight-character string constant
+// "23:59:01", or (if cannot determine time) "??:??:??"
+#define __TIME_HOUR_INT__ ( \
+ (__TIME__ [0u] == '?' ? 0u : __TIME__ [0u] - '0') * 10u \
+ + (__TIME__ [1u] == '?' ? 0u : __TIME__ [1u] - '0') )
+
+#define __TIME_MINUTE_INT__ ( \
+ (__TIME__ [3u] == '?' ? 0u : __TIME__ [3u] - '0') * 10u \
+ + (__TIME__ [4u] == '?' ? 0u : __TIME__ [4u] - '0') )
+
+#define __TIME_SECONDS_INT__ ( \
+ (__TIME__ [6u] == '?' ? 0u : __TIME__ [6u] - '0') * 10u \
+ + (__TIME__ [7u] == '?' ? 0u : __TIME__ [7u] - '0') )
+
+
+#define __DATE_MSDOS_INT__ ( \
+ ((__DATE_YEAR_INT__ - 1980u) << 9u) | \
+ ( __DATE_MONTH_INT__ << 5u) | \
+ ( __DATE_DAY_INT__ << 0u) )
+
+#define __TIME_MSDOS_INT__ ( \
+ ( __TIME_HOUR_INT__ << 11u) | \
+ ( __TIME_MINUTE_INT__ << 5u) | \
+ ( __TIME_SECONDS_INT__ << 0u) )
+
+__COMPILE_DATE_H_CONSTEXPR
+static const char __DATE_ISO8601_DATE__[] =
+{
+ (char)(( (__DATE_YEAR_INT__ / 1000) % 10 ) + '0'),
+ (char)(( (__DATE_YEAR_INT__ / 100) % 10 ) + '0'),
+ (char)(( (__DATE_YEAR_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__DATE_YEAR_INT__ / 1) % 10 ) + '0'),
+ '-',
+ (char)(( (__DATE_MONTH_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__DATE_MONTH_INT__ / 1) % 10 ) + '0'),
+ '-',
+ (char)(( (__DATE_DAY_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__DATE_DAY_INT__ / 1) % 10 ) + '0'),
+ '\0'
+};
+
+__COMPILE_DATE_H_CONSTEXPR
+const char __DATE_ISO8601_DATETIME__[] =
+{
+ (char)(( (__DATE_YEAR_INT__ / 1000) % 10 ) + '0'),
+ (char)(( (__DATE_YEAR_INT__ / 100) % 10 ) + '0'),
+ (char)(( (__DATE_YEAR_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__DATE_YEAR_INT__ / 1) % 10 ) + '0'),
+ '-',
+ (char)(( (__DATE_MONTH_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__DATE_MONTH_INT__ / 1) % 10 ) + '0'),
+ '-',
+ (char)(( (__DATE_DAY_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__DATE_DAY_INT__ / 1) % 10 ) + '0'),
+ 'T',
+ (char)(( (__TIME_HOUR_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__TIME_HOUR_INT__ / 1) % 10 ) + '0'),
+ ':',
+ (char)(( (__TIME_MINUTE_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__TIME_MINUTE_INT__ / 1) % 10 ) + '0'),
+ ':',
+ (char)(( (__TIME_SECONDS_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__TIME_SECONDS_INT__ / 1) % 10 ) + '0'),
+ '\0'
+};
+#endif // COMPILE_DATE_H
diff --git a/esp8266-fastled-webserver/include/simplehacks/constexpr_strlen.h b/esp8266-fastled-webserver/include/simplehacks/constexpr_strlen.h
new file mode 100644
index 00000000..b0e3703f
--- /dev/null
+++ b/esp8266-fastled-webserver/include/simplehacks/constexpr_strlen.h
@@ -0,0 +1,63 @@
+/**
+
+The MIT License (MIT)
+
+Copyright (c) SimpleHacks, Henry Gabryjelski
+https://github.com/SimpleHacks/UtilHeaders
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+*/
+
+#ifndef CONSTEXPR_STRLEN_H
+#define CONSTEXPR_STRLEN_H
+
+// avr gcc 5.4 and higher
+// clang 3.3 and higher, using -std=c++11
+// gcc 5.4 and higher, using -std=c++11
+// msvc 19.15 and higher
+template< size_t N >
+constexpr inline size_t constexpr_strlen( char const (&)[N] )
+{
+ return N-1;
+}
+
+#if __cpp_constexpr >= 201603
+ // avr gcc -- not supported (as of v 5.4.0)
+ // msvc -- not supported (as of v 19.22)
+ // gcc 7.2.1 and higher, using -std=c++17
+ // clang 5.0.0 and higher, using -std=c++17
+ constexpr inline size_t constexpr_strlen( const char* s )
+ {
+ return (
+ (0 == s) ? 0 :
+ (*s == '\0') ? 0 :
+ 1 + constexpr_strlen((const char*)(s+1))
+ );
+ }
+#endif
+
+
+
+
+#endif // #ifndef CONSTEXPR_STRLEN_H
+
+
diff --git a/esp8266-fastled-webserver/include/simplehacks/integer_seq.h b/esp8266-fastled-webserver/include/simplehacks/integer_seq.h
new file mode 100644
index 00000000..cba9e81c
--- /dev/null
+++ b/esp8266-fastled-webserver/include/simplehacks/integer_seq.h
@@ -0,0 +1,150 @@
+/**
+
+The MIT License (MIT)
+
+Copyright (c) SimpleHacks, Henry Gabryjelski
+https://github.com/SimpleHacks/UtilHeaders
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+*/
+
+#ifndef SIMPLEHACKS_INTEGER_SEQ_H
+#define SIMPLEHACKS_INTEGER_SEQ_H
+
+#include
+#include
+#include
+
+// A C++11 implementation of std::integer_sequence from C++14
+//
+// Two simpler examples:
+//
+// // Create sequence of values from 0 ... 255, as type uint8_t:
+// auto sequence = SimpleHacks::CompileTime::make_integer_sequence
+//
+// // Create size_t values from 0 ... 100:
+// auto sequence = SimpleHacks::CompileTime::make_index_sequenc( 100 );
+//
+namespace SimpleHacks {
+namespace CompileTime {
+
+ // Represents a compile-time sequence of integers.
+ // When used as an argument to a function template,
+ // the parameter pack Ints can be deduced and used in pack expansion.
+ template
+ struct integer_sequence {
+ static_assert( std::is_integral::value, "Integral type" );
+ using type = T;
+
+ static constexpr T size = sizeof...(I);
+
+ /// Generate an integer_sequence with an additional element.
+ template
+ using append = integer_sequence;
+
+ using next = append;
+ };
+ // C++11 rules require the static constexpr variable to be instantiated outside the template
+ template
+ constexpr T integer_sequence::size;
+
+ // ALIAS: index_sequence ==> integer_sequence
+ template
+ using index_sequence = integer_sequence;
+
+ // intended as private namespace to hide details from auto-completion and the like
+ namespace _Detail
+ {
+ // Metafunction that generates an integer_sequence of T containing [0, N)
+ template
+ struct iota
+ {
+ static_assert( Nt >= 0, "N cannot be negative" );
+ using type = typename iota::type::next;
+ };
+
+ // Terminal case of the recursive metafunction.
+ template
+ struct iota
+ {
+ using type = integer_sequence;
+ };
+ }
+
+ // Simplify creation of std::integer_sequence and std::index_sequence types with 0, 1, 2, ..., N-1 as Ints
+ // ALIAS: make_integer_sequence ==> integer_sequence
+ template
+ using make_integer_sequence = typename _Detail::iota::type;
+
+ // Simplify creation for the common case where T is std::size_t
+ // ALIAS: make_index_sequence ==> make_integer_sequence
+ // ==> integer_sequence
+ template
+ using make_index_sequence = make_integer_sequence;
+
+ // Convert any type parameter pack into an index sequence of the same length
+ // ALIAS: index_sequence_for<...> ==> make_index_sequence
+ // ==> make_integer_sequence
+ // ==> integer_sequence
+ template
+ using index_sequence_for = make_index_sequence;
+
+} // namespace CompileTime
+} // namespace SimpleHacks
+
+#endif // SIMPLEHACKS_INTEGER_SEQ_H
+
+/*
+ The concepts are based on a file published by Jonathan Wakely.
+ Without comment on its necessity, the following text is provided
+ for your reference.
+*/
+/*
+ Copyright Jonathan Wakely 2012-2013
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt)
+
+ Boost Software License - Version 1.0 - August 17th, 2003
+
+ Permission is hereby granted, free of charge, to any person or organization
+ obtaining a copy of the software and accompanying documentation covered by
+ this license (the "Software") to use, reproduce, display, distribute,
+ execute, and transmit the Software, and to prepare derivative works of the
+ Software, and to permit third-parties to whom the Software is furnished to
+ do so, all subject to the following:
+
+ The copyright notices in the Software and this entire statement, including
+ the above license grant, this restriction and the following disclaimer,
+ must be included in all copies of the Software, in whole or in part, and
+ all derivative works of the Software, unless such copies or derivative
+ works are solely in the form of machine-executable object code generated by
+ a source language processor.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+ SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+ FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+*/
diff --git a/esp8266-fastled-webserver/include/simplehacks/static_eval.h b/esp8266-fastled-webserver/include/simplehacks/static_eval.h
new file mode 100644
index 00000000..c5e9c1aa
--- /dev/null
+++ b/esp8266-fastled-webserver/include/simplehacks/static_eval.h
@@ -0,0 +1,50 @@
+/**
+
+The MIT License (MIT)
+
+Copyright (c) SimpleHacks, Henry Gabryjelski
+https://github.com/SimpleHacks/UtilHeaders
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+*/
+
+#ifndef STATIC_EVAL_H
+#define STATIC_EVAL_H
+
+// use to ensure static evaluation occcurs. e.g.,
+// #include // also in this repository
+// if (static_eval::value > 7) {
+// ....
+// }
+
+// avr gcc 5.4 and higher
+// clang 3.3 and higher, using -std=c++11
+// gcc 5.4 and higher, using -std=c++11
+// msvc 19.15 and higher
+template
+struct static_eval
+{
+ static constexpr T value = V;
+};
+
+#endif // #ifndef STATIC_EVAL_H
+
diff --git a/esp8266-fastled-webserver/include/simplehacks/timestamp.h b/esp8266-fastled-webserver/include/simplehacks/timestamp.h
new file mode 100644
index 00000000..a7f5362b
--- /dev/null
+++ b/esp8266-fastled-webserver/include/simplehacks/timestamp.h
@@ -0,0 +1,126 @@
+/**
+
+The MIT License (MIT)
+
+Copyright (c) SimpleHacks, Henry Gabryjelski
+https://github.com/SimpleHacks/UtilHeaders
+
+All rights reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+*/
+
+#ifndef TIMESTAMP_H
+#define TIMESTAMP_H
+
+// see https://godbolt.org/z/H7WC_4
+
+
+// presume support for `constexpr`
+#define __TIMESTAMP_H_CONSTEXPR constexpr
+
+#define __TIMESTAMP_YEAR_INT__ ((( \
+ (__TIMESTAMP__ [20u] - '0') * 10u + \
+ (__TIMESTAMP__ [21u] - '0')) * 10u + \
+ (__TIMESTAMP__ [22u] - '0')) * 10u + \
+ (__TIMESTAMP__ [23u] - '0'))
+
+#define __TIMESTAMP_MONTH_INT__ ( \
+ (__TIMESTAMP__ [6u] == 'n' && __TIMESTAMP__ [5u] == 'a') ? 1u /*Jan*/ \
+: (__TIMESTAMP__ [6u] == 'b' ) ? 2u /*Feb*/ \
+: (__TIMESTAMP__ [6u] == 'r' && __TIMESTAMP__ [5u] == 'a') ? 3u /*Mar*/ \
+: (__TIMESTAMP__ [6u] == 'r' ) ? 4u /*Apr*/ \
+: (__TIMESTAMP__ [6u] == 'y' ) ? 5u /*May*/ \
+: (__TIMESTAMP__ [6u] == 'n' ) ? 6u /*Jun*/ \
+: (__TIMESTAMP__ [6u] == 'l' ) ? 7u /*Jul*/ \
+: (__TIMESTAMP__ [6u] == 'g' ) ? 8u /*Aug*/ \
+: (__TIMESTAMP__ [6u] == 'p' ) ? 9u /*Sep*/ \
+: (__TIMESTAMP__ [6u] == 't' ) ? 10u /*Oct*/ \
+: (__TIMESTAMP__ [6u] == 'v' ) ? 11u /*Nov*/ \
+: 12u /*Dec*/ )
+
+#define __TIMESTAMP_DAY_INT__ ( \
+ (__TIMESTAMP__ [4u] == ' ' ? 0u : __TIMESTAMP__ [4u] - '0') * 10u \
+ + (__TIMESTAMP__ [5u] - '0') )
+
+
+#define __TIMESTAMP_HOUR_INT__ ( \
+ (__TIMESTAMP__ [11u] == '?' ? 0u : __TIMESTAMP__ [11u] - '0') * 10u \
+ + (__TIMESTAMP__ [12u] == '?' ? 0u : __TIMESTAMP__ [12u] - '0') )
+
+#define __TIMESTAMP_MINUTE_INT__ ( \
+ (__TIMESTAMP__ [14u] == '?' ? 0u : __TIMESTAMP__ [14u] - '0') * 10u \
+ + (__TIMESTAMP__ [15u] == '?' ? 0u : __TIMESTAMP__ [15u] - '0') )
+
+#define __TIMESTAMP_SECONDS_INT__ ( \
+ (__TIMESTAMP__ [17u] == '?' ? 0u : __TIMESTAMP__ [17u] - '0') * 10u \
+ + (__TIMESTAMP__ [18u] == '?' ? 0u : __TIMESTAMP__ [18u] - '0') )
+
+
+#define __TIMESTAMP_MSDOS_DATE_INT__ ( \
+ ((__TIMESTAMP_YEAR_INT__ - 1980u) << 9u) | \
+ ( __TIMESTAMP_MONTH_INT__ << 5u) | \
+ ( __TIMESTAMP_DAY_INT__ << 0u) )
+
+#define __TIMESTAMP_MSDOS_TIME_INT__ ( \
+ ( __TIMESTAMP_HOUR_INT__ << 11u) | \
+ ( __TIMESTAMP_MINUTE_INT__ << 5u) | \
+ ( __TIMESTAMP_SECONDS_INT__ << 0u) )
+
+__TIMESTAMP_H_CONSTEXPR
+static const char __TIMESTAMP_ISO8601_DATE__[] =
+{
+ (char)(( (__TIMESTAMP_YEAR_INT__ / 1000) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_YEAR_INT__ / 100) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_YEAR_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_YEAR_INT__ / 1) % 10 ) + '0'),
+ '-',
+ (char)(( (__TIMESTAMP_MONTH_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_MONTH_INT__ / 1) % 10 ) + '0'),
+ '-',
+ (char)(( (__TIMESTAMP_DAY_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_DAY_INT__ / 1) % 10 ) + '0'),
+ '\0'
+};
+__TIMESTAMP_H_CONSTEXPR
+const char __TIMESTAMP_ISO8601_DATETIME__[] =
+{
+ (char)(( (__TIMESTAMP_YEAR_INT__ / 1000) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_YEAR_INT__ / 100) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_YEAR_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_YEAR_INT__ / 1) % 10 ) + '0'),
+ '-',
+ (char)(( (__TIMESTAMP_MONTH_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_MONTH_INT__ / 1) % 10 ) + '0'),
+ '-',
+ (char)(( (__TIMESTAMP_DAY_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_DAY_INT__ / 1) % 10 ) + '0'),
+ 'T',
+ (char)(( (__TIMESTAMP_HOUR_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_HOUR_INT__ / 1) % 10 ) + '0'),
+ ':',
+ (char)(( (__TIMESTAMP_MINUTE_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_MINUTE_INT__ / 1) % 10 ) + '0'),
+ ':',
+ (char)(( (__TIMESTAMP_SECONDS_INT__ / 10) % 10 ) + '0'),
+ (char)(( (__TIMESTAMP_SECONDS_INT__ / 1) % 10 ) + '0'),
+ '\0'
+};
+#endif // TIMESTAMP_H