From 7aecb6ce65ec9c98e1caf888a589a8d90182f664 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Wed, 13 Oct 2021 20:57:43 -0700 Subject: [PATCH 01/16] Squashed commit from combined_dev: * Created common.h for headers This will allow renaming `.h` files that are really `.cpp` files, and is a stepping stone towards PlatformIO. * Split configuration options between product (e.g., default, Fibonacci256, etc.) and controller board (e.g., QT Py, ESP32, etc.) * Set default product to blank in HTML pages * Marked Fibonacci maps as constant * More palettes generated at compile-time * Naming -- Pixels represents a single controllable dot with 3 (RGB) or more (4 for RGBW, 5+ for others) LEDs internally. LED !== Pixel * Add some utility headers to simplify compile-time validation. --- .gitignore | 3 +- .../ColorWavesPlayground.h | 20 +- esp8266-fastled-webserver/Fields.h | 29 +- esp8266-fastled-webserver/GradientPalettes.h | 3 +- esp8266-fastled-webserver/Info.h | 47 ++ esp8266-fastled-webserver/Map.h | 388 +++++++++++ esp8266-fastled-webserver/Noise.h | 201 ++++++ esp8266-fastled-webserver/Pacifica.h | 158 +++++ esp8266-fastled-webserver/PridePlayground.h | 21 +- esp8266-fastled-webserver/TwinkleFOX.h | 2 +- esp8266-fastled-webserver/Twinkles.h | 6 +- esp8266-fastled-webserver/common.h | 107 +++ esp8266-fastled-webserver/config.h | 130 ++++ esp8266-fastled-webserver/data/index.htm | 5 +- esp8266-fastled-webserver/data/info.htm | 78 +++ esp8266-fastled-webserver/data/js/app.js | 10 + esp8266-fastled-webserver/data/js/info.js | 81 +++ esp8266-fastled-webserver/data/simple.htm | 2 + .../esp8266-fastled-webserver.ino | 608 ++++++++++++++---- .../configs/controller/controller_esp32.h | 30 + .../configs/controller/controller_esp8266.h | 32 + .../configs/controller/controller_template.h | 45 ++ .../include/configs/product/default.h | 35 + .../include/configs/product/fibonacci256.h | 38 ++ .../configs/product/product_template.h | 87 +++ .../include/simplehacks/array_size2.h | 147 +++++ .../include/simplehacks/compile_date.h | 136 ++++ .../include/simplehacks/constexpr_strlen.h | 63 ++ .../include/simplehacks/integer_seq.h | 150 +++++ .../include/simplehacks/static_eval.h | 50 ++ .../include/simplehacks/timestamp.h | 126 ++++ 31 files changed, 2697 insertions(+), 141 deletions(-) create mode 100644 esp8266-fastled-webserver/Info.h create mode 100644 esp8266-fastled-webserver/Map.h create mode 100644 esp8266-fastled-webserver/Noise.h create mode 100644 esp8266-fastled-webserver/Pacifica.h create mode 100644 esp8266-fastled-webserver/common.h create mode 100644 esp8266-fastled-webserver/config.h create mode 100644 esp8266-fastled-webserver/data/info.htm create mode 100644 esp8266-fastled-webserver/data/js/info.js create mode 100644 esp8266-fastled-webserver/include/configs/controller/controller_esp32.h create mode 100644 esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h create mode 100644 esp8266-fastled-webserver/include/configs/controller/controller_template.h create mode 100644 esp8266-fastled-webserver/include/configs/product/default.h create mode 100644 esp8266-fastled-webserver/include/configs/product/fibonacci256.h create mode 100644 esp8266-fastled-webserver/include/configs/product/product_template.h create mode 100644 esp8266-fastled-webserver/include/simplehacks/array_size2.h create mode 100644 esp8266-fastled-webserver/include/simplehacks/compile_date.h create mode 100644 esp8266-fastled-webserver/include/simplehacks/constexpr_strlen.h create mode 100644 esp8266-fastled-webserver/include/simplehacks/integer_seq.h create mode 100644 esp8266-fastled-webserver/include/simplehacks/static_eval.h create mode 100644 esp8266-fastled-webserver/include/simplehacks/timestamp.h diff --git a/.gitignore b/.gitignore index 249fd4d6..713f0297 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ build/ buildcache/ arduino.json c_cpp_properties.json -.vscode \ No newline at end of file +.vscode +/platformio-override.ini \ No newline at end of file diff --git a/esp8266-fastled-webserver/ColorWavesPlayground.h b/esp8266-fastled-webserver/ColorWavesPlayground.h index 12411f54..6c1b64e9 100644 --- a/esp8266-fastled-webserver/ColorWavesPlayground.h +++ b/esp8266-fastled-webserver/ColorWavesPlayground.h @@ -4,7 +4,7 @@ // Modified by Jason Coon to replace "magic numbers" with customizable inputs via sliders in the web app. -void colorwavesPlayground( CRGB* ledarray, uint16_t numleds, CRGBPalette16& palette) +void colorwavesPlayground( CRGB* ledarray, uint16_t numleds, CRGBPalette16& palette, bool useFibonacciOrder) { static uint16_t sPseudotime = 0; static uint16_t sLastMillis = 0; @@ -50,6 +50,13 @@ void colorwavesPlayground( CRGB* ledarray, uint16_t numleds, CRGBPalette16& pale 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); @@ -58,5 +65,14 @@ void colorwavesPlayground( CRGB* ledarray, uint16_t numleds, CRGBPalette16& pale void colorWavesPlayground() { - colorwavesPlayground(leds, NUM_LEDS, gCurrentPalette); + colorwavesPlayground(leds, NUM_PIXELS, gCurrentPalette, false); } + + +#if IS_FIBONACCI +void colorWavesPlaygroundFibonacci() +{ + colorwavesPlayground(leds, NUM_PIXELS, gCurrentPalette, true); +} +#endif + diff --git a/esp8266-fastled-webserver/Fields.h b/esp8266-fastled-webserver/Fields.h index b324c1d3..3843a226 100644 --- a/esp8266-fastled-webserver/Fields.h +++ b/esp8266-fastled-webserver/Fields.h @@ -81,6 +81,28 @@ String getAutoplayDuration() { return String(autoplayDuration); } +String getShowClock() { + return String(showClock); +} + +String getClockBackgroundFade() { + return String(clockBackgroundFade); +} + +void setShowClock(uint8_t value) +{ + showClock = value == 0 ? 0 : 1; + writeAndCommitSettings(); + broadcastInt("showClock", showClock); +} + +void setClockBackgroundFade(uint8_t value) +{ + clockBackgroundFade = value; + writeAndCommitSettings(); + broadcastInt("clockBackgroundFade", clockBackgroundFade); +} + String getSolidColor() { return String(solidColor.r) + "," + String(solidColor.g) + "," + String(solidColor.b); } @@ -257,6 +279,11 @@ FieldList fields = { {"autoplay", "Autoplay", BooleanFieldType, 0, 1, getAutoplay, nullptr, nullptr}, {"autoplayDuration", "Autoplay Duration", NumberFieldType, 0, 255, getAutoplayDuration, nullptr, nullptr}, + //-------------------------------------------------------------------------------------------------------- + {"clock", "Clock", SectionFieldType, 0, 0, nullptr, nullptr, nullptr}, + {"showClock", "Show Clock", BooleanFieldType, 0, 1, getShowClock, nullptr, nullptr}, + {"clockBackgroundFade", "Background Fade", NumberFieldType, 0, 255, getClockBackgroundFade, nullptr, nullptr}, + //-------------------------------------------------------------------------------------------------------- {"solidColorSection", "Solid Color", SectionFieldType, 0, 0, nullptr, nullptr, nullptr}, {"solidColor", "Color", ColorFieldType, 0, 255, getSolidColor, nullptr, nullptr}, @@ -301,4 +328,4 @@ FieldList fields = { {"sHueMax", "S Hue Max", NumberFieldType, 0, 255, getSHueMax, nullptr, setSHueMax}, }; -uint8_t fieldCount = ARRAY_SIZE(fields); +uint8_t fieldCount = ARRAY_SIZE2(fields); diff --git a/esp8266-fastled-webserver/GradientPalettes.h b/esp8266-fastled-webserver/GradientPalettes.h index 9928500c..c9d6eb2b 100644 --- a/esp8266-fastled-webserver/GradientPalettes.h +++ b/esp8266-fastled-webserver/GradientPalettes.h @@ -513,6 +513,5 @@ const TProgmemRGBGradientPalettePtr gGradientPalettes[] = { // Count of how many cpt-city gradients are defined: -const uint8_t gGradientPaletteCount = - sizeof( gGradientPalettes) / sizeof( TProgmemRGBGradientPalettePtr ); +const uint8_t gGradientPaletteCount = ARRAY_SIZE2(gGradientPalettes); diff --git a/esp8266-fastled-webserver/Info.h b/esp8266-fastled-webserver/Info.h new file mode 100644 index 00000000..0be3f50c --- /dev/null +++ b/esp8266-fastled-webserver/Info.h @@ -0,0 +1,47 @@ +String WiFi_SSID(bool persistent) { + struct station_config conf; + if(persistent) wifi_station_get_config_default(&conf); + else wifi_station_get_config(&conf); + + const size_t buffer_len = sizeof(conf.ssid)+1; //ssid can be up to 32chars, => plus null term + char tmp[buffer_len]; + memcpy(tmp, conf.ssid, sizeof(conf.ssid)); + tmp[buffer_len-1] = 0; //nullterm in case of 32 char ssid + return String(reinterpret_cast(tmp)); +} + +String getInfoJson() +{ + String json = "{"; + json += "\"millis\":" + (String)millis() + ","; + json += "\"vcc\":" + (String)ESP.getVcc() + ","; + json += "\"wiFiChipId\":\"" + String(WIFI_getChipId(), HEX) + "\","; + json += "\"flashChipId\":\"" + String(ESP.getFlashChipId(), HEX) + "\","; + json += "\"flashChipSize\":" + (String)ESP.getFlashChipSize() + ","; + json += "\"flashChipRealSize\":" + (String)ESP.getFlashChipRealSize() + ","; + json += "\"sdkVersion\":\"" + (String)system_get_sdk_version() + "\","; + json += "\"coreVersion\":\"" + (String)ESP.getCoreVersion() + "\","; + json += "\"bootVersion\":" + (String)system_get_boot_version() + ","; + json += "\"cpuFreqMHz\":" + (String)ESP.getCpuFreqMHz() + ","; + json += "\"freeHeap\":" + (String)ESP.getFreeHeap() + ","; + json += "\"sketchSize\":" + (String)ESP.getSketchSize() + ","; + json += "\"freeSketchSpace\":" + (String)ESP.getFreeSketchSpace() + ","; + json += "\"resetReason\":\"" + (String)ESP.getResetReason() + "\","; + json += "\"isConnected\":" + (WiFi.isConnected() ? String("true") : String("false")) + ","; + json += "\"wiFiSsidDefault\":\"" + (String)WiFi_SSID(true) + "\","; + json += "\"wiFiSSID\":\"" + (String)WiFi_SSID(false) + "\","; + json += "\"localIP\":\"" + WiFi.localIP().toString() + "\","; + json += "\"gatewayIP\":\"" + WiFi.gatewayIP().toString() + "\","; + json += "\"subnetMask\":\"" + WiFi.subnetMask().toString() + "\","; + json += "\"dnsIP\":\"" + WiFi.dnsIP().toString() + "\","; + json += "\"hostname\":\"" + WiFi.hostname() + "\","; + json += "\"macAddress\":\"" + WiFi.macAddress() + "\","; + json += "\"autoConnect\":" + (WiFi.getAutoConnect() ? String("true") : String("false")) + ","; + json += "\"softAPSSID\":\"" + WiFi.softAPSSID() + "\","; + json += "\"softAPIP\":\"" + WiFi.softAPIP().toString() + "\","; + json += "\"BSSID\":\"" + (String)WiFi.BSSIDstr() + "\","; + json += "\"softAPmacAddress\":\"" + (String)WiFi.softAPmacAddress() + "\""; + json += "}"; + + return json; +} diff --git a/esp8266-fastled-webserver/Map.h b/esp8266-fastled-webserver/Map.h new file mode 100644 index 00000000..d5aba8fe --- /dev/null +++ b/esp8266-fastled-webserver/Map.h @@ -0,0 +1,388 @@ +#if IS_FIBONACCI + +// Each Fibonacci board must define the following arrays: +// +// physicalToFibonacci[] === physical LED order to ordered by radius (vogel spiral order) +// fibonacciToPhysical[] === radius (vogel spiral order) to physical LED order +// angles[] === angle, where the range is from 0..255 for entire circle +// coordsX[] / coordsY[] === uint8_t coordinates for transformed spiral +// +// All boards appear to use the vogel model, with offset to first point == 0. +// [[ This can be confirmed by first element of angles[] === 0, +// i.e., the first point is the center of the spiral at origin (x=0, y=0) +// ]] +// +// Once all the LEDs actual positions are calculated, transform the original +// coordinates to fit the uint8_t coordinates used: +// +// 1. Translate the spiral so minimum X value is zero (shift right) +// 2. Translate the spiral so minimum Y value is zero (shift up) +// 3. Scale the resulting spiral so maximum X / Y value is 255. +// +// The resulting coordinates are then stored in the coordsX/Y ranges, +// to allow for faster (8-bit) math operations on lower-power MCUs. +// + +#if defined(PRODUCT_FIBONACCI256) + const uint16_t physicalToFibonacci[NUM_PIXELS] = { 0, 13, 26, 39, 52, 65, 78, 91, 104, 117, 130, 143, 156, 169, 182, 195, 208, 221, 234, 247, 252, 239, 226, 213, 200, 187, 174, 161, 148, 135, 122, 109, 96, 83, 70, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 75, 88, 101, 114, 127, 140, 153, 166, 179, 192, 205, 218, 231, 244, 249, 236, 223, 210, 197, 184, 171, 158, 145, 132, 119, 106, 93, 80, 67, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189, 202, 215, 228, 241, 254, 246, 233, 220, 207, 194, 181, 168, 155, 142, 129, 116, 103, 90, 77, 64, 51, 38, 25, 12, 4, 17, 30, 43, 56, 69, 82, 95, 108, 121, 134, 147, 160, 173, 186, 199, 212, 225, 238, 251, 243, 230, 217, 204, 191, 178, 165, 152, 139, 126, 113, 100, 87, 74, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 66, 79, 92, 105, 118, 131, 144, 157, 170, 183, 196, 209, 222, 235, 248, 253, 240, 227, 214, 201, 188, 175, 162, 149, 136, 123, 110, 97, 84, 71, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 76, 89, 102, 115, 128, 141, 154, 167, 180, 193, 206, 219, 232, 245, 250, 237, 224, 211, 198, 185, 172, 159, 146, 133, 120, 107, 94, 81, 68, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60, 73, 86, 99, 112, 125, 138, 151, 164, 177, 190, 203, 216, 229, 242, 255 }; + const uint16_t fibonacciToPhysical[NUM_PIXELS] = { 0, 157, 78, 235, 118, 39, 196, 79, 236, 156, 40, 197, 117, 1, 158, 77, 234, 119, 38, 195, 80, 237, 155, 41, 198, 116, 2, 159, 76, 233, 120, 37, 194, 81, 238, 154, 42, 199, 115, 3, 160, 75, 232, 121, 36, 193, 82, 239, 153, 43, 200, 114, 4, 161, 74, 231, 122, 35, 192, 83, 240, 152, 44, 201, 113, 5, 162, 73, 230, 123, 34, 191, 84, 241, 151, 45, 202, 112, 6, 163, 72, 229, 124, 33, 190, 85, 242, 150, 46, 203, 111, 7, 164, 71, 228, 125, 32, 189, 86, 243, 149, 47, 204, 110, 8, 165, 70, 227, 126, 31, 188, 87, 244, 148, 48, 205, 109, 9, 166, 69, 226, 127, 30, 187, 88, 245, 147, 49, 206, 108, 10, 167, 68, 225, 128, 29, 186, 89, 246, 146, 50, 207, 107, 11, 168, 67, 224, 129, 28, 185, 90, 247, 145, 51, 208, 106, 12, 169, 66, 223, 130, 27, 184, 91, 248, 144, 52, 209, 105, 13, 170, 65, 222, 131, 26, 183, 92, 249, 143, 53, 210, 104, 14, 171, 64, 221, 132, 25, 182, 93, 250, 142, 54, 211, 103, 15, 172, 63, 220, 133, 24, 181, 94, 251, 141, 55, 212, 102, 16, 173, 62, 219, 134, 23, 180, 95, 252, 140, 56, 213, 101, 17, 174, 61, 218, 135, 22, 179, 96, 253, 139, 57, 214, 100, 18, 175, 60, 217, 136, 21, 178, 97, 254, 138, 58, 215, 99, 19, 176, 59, 216, 137, 20, 177, 98, 255 }; + const uint8_t coordsX[NUM_PIXELS] = { 133, 156, 165, 168, 165, 158, 147, 132, 114, 95, 76, 57, 41, 28, 19, 15, 17, 24, 37, 56, 123, 96, 73, 53, 38, 28, 24, 25, 31, 41, 55, 71, 89, 106, 122, 136, 146, 152, 152, 143, 138, 136, 128, 115, 101, 85, 70, 56, 44, 37, 33, 34, 41, 53, 69, 90, 114, 140, 167, 226, 204, 180, 154, 129, 106, 85, 67, 54, 46, 43, 44, 50, 60, 72, 86, 100, 113, 123, 128, 117, 104, 90, 78, 67, 59, 54, 54, 59, 68, 82, 100, 121, 143, 167, 191, 212, 231, 246, 255, 251, 251, 245, 233, 218, 199, 178, 156, 134, 114, 96, 82, 73, 67, 66, 70, 78, 89, 103, 111, 94, 84, 80, 81, 86, 96, 109, 126, 145, 165, 185, 204, 220, 233, 241, 244, 241, 232, 217, 179, 201, 217, 229, 235, 235, 230, 220, 207, 190, 172, 154, 136, 121, 108, 99, 95, 96, 104, 120, 110, 111, 118, 130, 144, 160, 176, 192, 206, 217, 224, 227, 224, 216, 202, 184, 162, 137, 110, 44, 68, 94, 120, 145, 168, 187, 202, 212, 216, 216, 212, 203, 191, 177, 162, 148, 135, 126, 122, 136, 147, 161, 174, 186, 197, 204, 206, 205, 198, 187, 172, 152, 130, 106, 81, 58, 36, 17, 0, 5, 15, 30, 49, 71, 93, 116, 138, 157, 173, 185, 192, 195, 193, 187, 178, 166, 152, 137, 149, 164, 175, 180, 182, 179, 171, 159, 143, 125, 105, 83, 63, 44, 28, 16, 9, 7, 12, 23 }; + const uint8_t coordsY[NUM_PIXELS] = { 126, 120, 109, 96, 82, 69, 57, 49, 45, 45, 50, 59, 74, 92, 114, 138, 163, 188, 211, 231, 255, 248, 235, 218, 198, 175, 152, 129, 107, 89, 74, 63, 57, 56, 59, 66, 76, 88, 102, 116, 103, 88, 77, 71, 68, 70, 77, 88, 103, 121, 141, 163, 184, 205, 222, 236, 245, 249, 247, 208, 224, 235, 241, 240, 234, 223, 209, 191, 172, 152, 132, 115, 101, 90, 84, 82, 86, 95, 114, 107, 98, 98, 103, 112, 126, 142, 159, 177, 195, 210, 222, 230, 233, 230, 223, 209, 191, 168, 142, 98, 125, 151, 174, 194, 209, 219, 223, 223, 218, 208, 195, 180, 164, 148, 134, 122, 114, 112, 123, 128, 138, 151, 165, 180, 193, 203, 211, 214, 212, 206, 194, 178, 158, 134, 109, 83, 58, 35, 11, 28, 48, 71, 95, 120, 142, 163, 179, 192, 200, 203, 202, 196, 187, 175, 162, 148, 136, 133, 152, 166, 177, 186, 190, 191, 187, 178, 165, 148, 128, 107, 84, 62, 41, 24, 11, 2, 0, 28, 16, 9, 8, 13, 23, 37, 55, 75, 96, 116, 135, 151, 164, 173, 177, 177, 172, 162, 146, 153, 161, 163, 160, 152, 139, 124, 106, 87, 69, 51, 36, 25, 18, 16, 20, 29, 44, 64, 133, 106, 81, 60, 44, 32, 26, 25, 29, 38, 50, 65, 82, 99, 115, 129, 140, 147, 148, 138, 134, 131, 122, 110, 95, 80, 65, 52, 42, 36, 34, 37, 45, 59, 77, 98, 123, 149, 176, 202 }; + const uint8_t angles[NUM_PIXELS] = { 0, 247, 238, 229, 220, 211, 203, 194, 185, 176, 167, 159, 150, 141, 132, 123, 115, 106, 97, 88, 65, 74, 83, 92, 100, 109, 118, 127, 136, 144, 153, 162, 171, 180, 188, 197, 206, 215, 224, 232, 209, 201, 192, 183, 174, 165, 157, 148, 139, 130, 121, 113, 104, 95, 86, 77, 69, 60, 51, 28, 37, 46, 54, 63, 72, 81, 90, 98, 107, 116, 125, 134, 142, 151, 160, 169, 178, 186, 195, 172, 163, 155, 146, 137, 128, 119, 111, 102, 93, 84, 75, 67, 58, 49, 40, 31, 23, 14, 5, 246, 255, 8, 17, 26, 35, 44, 52, 61, 70, 79, 88, 96, 105, 114, 123, 132, 140, 149, 135, 126, 117, 108, 100, 91, 82, 73, 64, 56, 47, 38, 29, 20, 12, 3, 250, 241, 232, 223, 209, 218, 227, 235, 244, 253, 6, 15, 24, 33, 41, 50, 59, 68, 77, 85, 94, 103, 112, 98, 89, 80, 71, 62, 54, 45, 36, 27, 18, 10, 1, 247, 239, 230, 221, 212, 203, 195, 186, 163, 172, 180, 189, 198, 207, 216, 224, 233, 242, 251, 4, 13, 22, 31, 39, 48, 57, 66, 75, 52, 43, 34, 25, 16, 8, 254, 245, 237, 228, 219, 210, 201, 193, 184, 175, 166, 157, 149, 126, 134, 143, 152, 161, 170, 178, 187, 196, 205, 214, 222, 231, 240, 249, 2, 11, 20, 28, 37, 14, 5, 252, 243, 235, 226, 217, 208, 199, 191, 182, 173, 164, 155, 147, 138, 129, 120, 111, 103 }; +#else + #error "Unknown / Unsupported fibonacci product ... no mappings defined" +#endif +static_assert(NUM_PIXELS == ARRAY_SIZE2(physicalToFibonacci), ""); +static_assert(NUM_PIXELS == ARRAY_SIZE2(fibonacciToPhysical), ""); +static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsX), ""); +static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsY), ""); +static_assert(NUM_PIXELS == ARRAY_SIZE2(angles), ""); + +void drawSpiralLine(uint8_t angle, int step, CRGB color) +{ + int startIndex = 0; + int smallestAngleDifference = 255; + + // find the outermost led closest to the desired angle + for (int i = 0; i < NUM_PIXELS; i++) { + int j = physicalToFibonacci[i]; + if (j < step) continue; + if (!(j + step >= NUM_PIXELS)) continue; // not outermost + uint8_t a = angles[i]; + if (a == angle) startIndex = i; + else if (angle - a > 0 && angle - a < smallestAngleDifference) { + smallestAngleDifference = angle - a; + startIndex = i; + } + } + + // draw the starting LED + leds[startIndex] += color; + + // draw to center from outer start + int f = physicalToFibonacci[startIndex]; + while (f - step >= 0 && f - step < NUM_PIXELS) { + leds[fibonacciToPhysical[f]] += color; + f = f - step; + } +} + +void setPixelAR(uint8_t angle, uint8_t dAngle, uint8_t radius, uint8_t dRadius, CRGB color) +{ + uint16_t amax = qadd8(angle, dAngle); + uint8_t amin = qsub8(angle, dAngle); + + uint16_t rmax = qadd8(radius, dRadius); + uint16_t rmin = qsub8(radius, dRadius); + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint8_t o = i; + + uint8_t ao = angles[o]; + + if (ao <= amax && ao >= amin) { + uint8_t ro = physicalToFibonacci[o]; + + if (ro <= rmax && ro >= rmin) { + leds[i] = color; + } + } + } +} + +void andPixelAR(uint8_t angle, uint8_t dAngle, uint8_t startRadius, uint8_t endRadius, CRGB color) +{ + uint16_t amax = qadd8(angle, dAngle); + uint8_t amin = qsub8(angle, dAngle); + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint8_t o = i; + + uint8_t ao = angles[o]; + + if (ao <= amax && ao >= amin) { + uint8_t ro = physicalToFibonacci[o]; + + if (ro <= endRadius && ro >= startRadius) { + leds[i] += color; + } + } + } +} + +void antialiasPixelAR(uint8_t angle, uint8_t dAngle, uint8_t startRadius, uint8_t endRadius, CRGB color, CRGB leds[] = leds, int _NUM_PIXELS = NUM_PIXELS) +{ + for (uint16_t i = 0; i < _NUM_PIXELS; i++) { + uint8_t o = i; + + uint8_t ao = angles[o]; + + uint8_t adiff = min(sub8(ao,angle), sub8(angle, ao)); + uint8_t fade = map(adiff, 0, dAngle, 0, 255); + CRGB faded = color; + faded.fadeToBlackBy(fade); + + if (adiff <= dAngle) { + uint8_t ro = physicalToFibonacci[o]; + + if (ro <= endRadius && ro >= startRadius) { + leds[i] += faded; + } + } + } +} + +void anglePalette() { + uint16_t hues = 1; + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t x = angles[i]; + + leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - (x * hues)); + } +} + +void radiusPalette() { + uint16_t hues = 1; + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t r = physicalToFibonacci[i]; + + leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - (r * hues)); + } +} + +void xPalette() { + uint16_t hues = 1; + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t x = coordsX[i]; + + leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - (x * hues)); + } +} + +void yPalette() { + uint16_t hues = 1; + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t y = coordsY[i]; + + leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - (y * hues)); + } +} + +void xyPalette() { + uint16_t hues = 1; + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t x = coordsX[i]; + uint16_t y = coordsY[i]; + + leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - ((x + y) * hues)); + } +} + +void angleGradientPalette() { + uint16_t hues = 1; + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t x = angles[i]; + + leds[i] = ColorFromPalette(gCurrentPalette, beat8(speed) - (x * hues)); + } +} + +void radiusGradientPalette() { + uint16_t hues = 1; + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t r = physicalToFibonacci[i]; + + leds[i] = ColorFromPalette(gCurrentPalette, beat8(speed) - (r * hues)); + } +} + +void xGradientPalette() { + uint16_t hues = 1; + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t x = coordsX[i]; + + leds[i] = ColorFromPalette(gCurrentPalette, beat8(speed) - (x * hues)); + } +} + +void yGradientPalette() { + uint16_t hues = 1; + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t y = coordsY[i]; + + leds[i] = ColorFromPalette(gCurrentPalette, beat8(speed) - (y * hues)); + } +} + +void xyGradientPalette() { + uint16_t hues = 1; + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t x = coordsX[i]; + uint16_t y = coordsY[i]; + + leds[i] = ColorFromPalette(gCurrentPalette, beat8(speed) - ((x + y) * hues)); + } +} + +// calls antialiasPixelAR, which requires physicalToFibonacci array) +void drawAnalogClock() { + float second = timeClient.getSeconds(); + float minute = timeClient.getMinutes() + (second / 60.0); + float hour = timeClient.getHours() + (minute / 60.0); + + const uint8_t hourRadius = 96; + const uint8_t minuteRadius = 192; + const uint8_t secondRadius = 255; + + const uint8_t hourHandWidth = 8; + const uint8_t minuteHandWidth = 7; + const uint8_t secondHandWidth = 6; + + const float degreesPerSecond = 255.0 / 60.0; + const float degreesPerMinute = 255.0 / 60.0; + const float degreesPerHour = 255.0 / 12.0; + + static uint8_t hourAngle = 255 - hour * degreesPerHour; + static uint8_t minuteAngle = 255 - minute * degreesPerMinute; + static uint8_t secondAngle = 255 - second * degreesPerSecond; + + EVERY_N_MILLIS(100) { + hourAngle = 64 - hour * degreesPerHour; + minuteAngle = 64 - minute * degreesPerMinute; + secondAngle = 64 - second * degreesPerSecond; + } + + fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); + + antialiasPixelAR(secondAngle, secondHandWidth, 0, secondRadius, CRGB::Blue); + antialiasPixelAR(minuteAngle, minuteHandWidth, 0, minuteRadius, CRGB::Green); + antialiasPixelAR(hourAngle, hourHandWidth, 0, hourRadius, CRGB::Red); + leds[0] = CRGB::Red; +} + +// TODO: Optimize this so more calculations are within EVERY_N_MILLIS(100) +// TODO: Allow configuration to disable the seconds hand +void drawSpiralAnalogClock(uint8_t step) { + float second = timeClient.getSeconds(); + float minute = timeClient.getMinutes() + (second / 60.0); + float hour = timeClient.getHours() + (minute / 60.0); + + static uint8_t hourAngle = 0; + static uint8_t minuteAngle = 0; + static uint8_t secondAngle = 0; + + const float degreesPerSecond = 255.0 / 60.0; + const float degreesPerMinute = 255.0 / 60.0; + const float degreesPerHour = 255.0 / 12.0; + + EVERY_N_MILLIS(100) { + hourAngle = 255 - hour * degreesPerHour; + minuteAngle = 255 - minute * degreesPerMinute; + secondAngle = 255 - second * degreesPerSecond; + } + + drawSpiralLine(secondAngle, step, CRGB(0, 0, 2)); + drawSpiralLine(minuteAngle, step, CRGB(0, 2, 0)); + drawSpiralLine(hourAngle, step, CRGB(2, 0, 0)); +} + +// reduces pattern by clockBackgroundFade, then draws clock hands +void drawSpiralAnalogClock13() { + fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); + drawSpiralAnalogClock(13); +} + +void drawSpiralAnalogClock21() { + fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); + drawSpiralAnalogClock(21); +} + +void drawSpiralAnalogClock34() { + fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); + drawSpiralAnalogClock(34); +} + +void drawSpiralAnalogClock55() { + fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); + drawSpiralAnalogClock(55); +} + +void drawSpiralAnalogClock89() { + fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); + drawSpiralAnalogClock(89); +} + +void drawSpiralAnalogClock21and34() { + fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); + drawSpiralAnalogClock(21); + drawSpiralAnalogClock(34); +} + +// TODO: Optimize this so more calculations are within EVERY_N_MILLIS(100) +// TODO: Allow configuration to disable the seconds hand +void drawSpiralAnalogClock13_21_and_34() { + float second = timeClient.getSeconds(); + float minute = timeClient.getMinutes() + (second / 60.0); + float hour = timeClient.getHours() + (minute / 60.0); + + static uint8_t hourAngle = 0; + static uint8_t minuteAngle = 0; + static uint8_t secondAngle = 0; + + const float degreesPerSecond = 255.0 / 60.0; + const float degreesPerMinute = 255.0 / 60.0; + const float degreesPerHour = 255.0 / 12.0; + + EVERY_N_MILLIS(100) { + hourAngle = 255 - hour * degreesPerHour; + minuteAngle = 255 - minute * degreesPerMinute; + secondAngle = 255 - second * degreesPerSecond; + } + + fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); + + drawSpiralLine(secondAngle, 13, CRGB(0, 0, 2)); + drawSpiralLine(minuteAngle, 21, CRGB(0, 2, 0)); + drawSpiralLine(hourAngle, 34, CRGB(2, 0, 0)); +} + +// TODO: Optimize this so more calculations are within EVERY_N_MILLIS(100) +// TODO: Allow configuration to disable the seconds hand +void drawSpiralAnalogClock34_21_and_13() { + float second = timeClient.getSeconds(); + float minute = timeClient.getMinutes() + (second / 60.0); + float hour = timeClient.getHours() + (minute / 60.0); + + static uint8_t hourAngle = 0; + static uint8_t minuteAngle = 0; + static uint8_t secondAngle = 0; + + const float degreesPerSecond = 255.0 / 60.0; + const float degreesPerMinute = 255.0 / 60.0; + const float degreesPerHour = 255.0 / 12.0; + + EVERY_N_MILLIS(100) { + hourAngle = 255 - hour * degreesPerHour; + minuteAngle = 255 - minute * degreesPerMinute; + secondAngle = 255 - second * degreesPerSecond; + } + + fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); + + drawSpiralLine(secondAngle, 34, CRGB(0, 0, 2)); + drawSpiralLine(minuteAngle, 21, CRGB(0, 2, 0)); + drawSpiralLine(hourAngle, 13, CRGB(2, 0, 0)); +} + + +#endif // IS_FIBONACCI diff --git a/esp8266-fastled-webserver/Noise.h b/esp8266-fastled-webserver/Noise.h new file mode 100644 index 00000000..e0eb2ee8 --- /dev/null +++ b/esp8266-fastled-webserver/Noise.h @@ -0,0 +1,201 @@ +/* + ESP8266 + FastLED: https://github.com/jasoncoon/esp8266-fastled-webserver + Copyright (C) 2015-2020 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 . +*/ + +// drawNoise() function uses coordsX / coordsY, which are only available for Fibonacci boards +#if IS_FIBONACCI + + +// TODO: static assert that the values here correspond to the maximum storable value +// used by the typeof(coordsX) and typeof(coordsY). +const uint8_t matrixWidth = 255; +const uint8_t matrixHeight = 255; + +#define MAX_DIMENSION ((matrixWidth > matrixHeight) ? matrixWidth : matrixHeight) + +// The larger (16-bit) version of our coordinates +static uint16_t noisex; +static uint16_t noisey; +static uint16_t noisez; + +// We're using the x/y dimensions to map to the x/y pixels on the matrix. We'll +// use the z-axis for "time". speed determines how fast time moves forward. Try +// 1 for a very slow moving effect, or 60 for something that ends up looking like +// water. +static int noisespeedx = 0; +static int noisespeedy = 1; +static int noisespeedz = 0; + +// Scale determines how far apart the pixels in our noise matrix are. Try +// changing these values around to see how it affects the motion of the display. The +// higher the value of scale, the more "zoomed out" the noise will be. A value +// of 1 will be so zoomed in, you'll mostly see solid colors. +static uint16_t noisescale = 1; // scale is set dynamically once we've started up + +static uint8_t colorLoop = 0; + +static const CRGBPalette16 blackAndWhiteStripedPalette { + CRGB::White, CRGB::Black, CRGB::Black, CRGB::Black, + CRGB::White, CRGB::Black, CRGB::Black, CRGB::Black, + CRGB::White, CRGB::Black, CRGB::Black, CRGB::Black, + CRGB::White, CRGB::Black, CRGB::Black, CRGB::Black +}; + +static const CRGBPalette16 blackAndBlueStripedPalette { + CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, + CRGB::Blue, CRGB::Blue, CRGB::Black, CRGB::Black, + CRGB::Black, CRGB::Black, CRGB::Black, CRGB::Black, + CRGB::Black, CRGB::Black, CRGB::Black, CRGB::Black +}; + +// There are several different palettes of colors demonstrated here. +// +// FastLED provides several 'preset' palettes: RainbowColors_p, RainbowStripeColors_p, +// OceanColors_p, CloudColors_p, LavaColors_p, ForestColors_p, and PartyColors_p. +// +// Additionally, you can manually define your own color palettes, or you can write +// code that creates color palettes on the fly. + +void drawNoise(CRGBPalette16 palette, uint8_t hueReduce = 0) +{ + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint16_t x = coordsX[i]; + uint16_t y = coordsY[i]; + + int xoffset = noisescale * x; + int yoffset = noisescale * y; + + uint8_t data = inoise8(x + xoffset + noisex, y + yoffset + noisey, noisez); + + // The range of the inoise8 function is roughly 16-238. + // These two operations expand those values out to roughly 0..255 + // You can comment them out if you want the raw noise data. + data = qsub8(data, 16); + data = qadd8(data, scale8(data, 39)); + + if (hueReduce > 0 && data >= hueReduce) + data -= hueReduce; + + leds[i] = ColorFromPalette(palette, data, 255, LINEARBLEND); + } + + noisex += noisespeedx; + noisey += noisespeedy; + noisez += noisespeedz; +} + +void rainbowNoise() { + noisespeedx = 0; + noisespeedy = -1; + noisespeedz = 0; + noisescale = 6; + colorLoop = 0; + drawNoise(RainbowColors_p); +} + +void rainbowStripeNoise() { + noisespeedx = 0; + noisespeedy = -2; + noisespeedz = 0; + noisescale = 6; + colorLoop = 0; + drawNoise(RainbowStripeColors_p); +} + +void partyNoise() { + noisespeedx = -9; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 8; + colorLoop = 0; + drawNoise(PartyColors_p); +} + +void forestNoise() { + noisespeedx = -9; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 8; + colorLoop = 0; + drawNoise(ForestColors_p); +} + +void cloudNoise() { + noisespeedx = -2; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 6; + colorLoop = 0; + drawNoise(CloudColors_p); +} + +void fireNoise() { + noisespeedx = 0; // 24; + noisespeedy = -32; + noisespeedz = 0; + noisescale = 16; + colorLoop = 0; + drawNoise(HeatColors_p, 60); +} + +void fireNoise2() { + noisespeedx = 0; + noisespeedy = -8; + noisespeedz = 3; + noisescale = 8; + colorLoop = 0; + drawNoise(HeatColors_p); +} + +void lavaNoise() { + noisespeedx = 0; + noisespeedy = -1; + noisespeedz = 1; + noisescale = 6; + colorLoop = 0; + drawNoise(LavaColors_p); +} + +void oceanNoise() { + noisespeedx = -2; + noisespeedy = 0; + noisespeedz = 4; + noisescale = 6; + colorLoop = 0; + drawNoise(OceanColors_p); +} + +void blackAndWhiteNoise() { + noisespeedx = -12; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 6; + colorLoop = 0; + drawNoise(blackAndWhiteStripedPalette); +} + +void blackAndBlueNoise() { + noisespeedx = 0; + noisespeedy = 8; + noisespeedz = 0; + noisescale = 8; + colorLoop = 0; + drawNoise(blackAndBlueStripedPalette); +} + + +#endif // IS_FIBONACCI \ No newline at end of file diff --git a/esp8266-fastled-webserver/Pacifica.h b/esp8266-fastled-webserver/Pacifica.h new file mode 100644 index 00000000..3ed81dc5 --- /dev/null +++ b/esp8266-fastled-webserver/Pacifica.h @@ -0,0 +1,158 @@ +// +// "Pacifica" +// Gentle, blue-green ocean waves. +// December 2019, Mark Kriegsman and Mary Corey March. +// For Dan. +// +// https://gist.github.com/kriegsman/36a1e277f5b4084258d9af1eae29bac4 +// + +////////////////////////////////////////////////////////////////////////// +// +// The code for this animation is more complicated than other examples, and +// while it is "ready to run", and documented in general, it is probably not +// the best starting point for learning. Nevertheless, it does illustrate some +// useful techniques. +// +////////////////////////////////////////////////////////////////////////// +// +// In this animation, there are four "layers" of waves of light. +// +// Each layer moves independently, and each is scaled separately. +// +// All four wave layers are added together on top of each other, and then +// another filter is applied that adds "whitecaps" of brightness where the +// waves line up with each other more. Finally, another pass is taken +// over the led array to 'deepen' (dim) the blues and greens. +// +// The speed and scale and motion each layer varies slowly within independent +// hand-chosen ranges, which is why the code has a lot of low-speed 'beatsin8' functions +// with a lot of oddly specific numeric ranges. +// +// These three custom blue-green color palettes were inspired by the colors found in +// the waters off the southern coast of California, https://goo.gl/maps/QQgd97jjHesHZVxQ7 +// +CRGBPalette16 pacifica_palette_1 = + { 0x000507, 0x000409, 0x00030B, 0x00030D, 0x000210, 0x000212, 0x000114, 0x000117, + 0x000019, 0x00001C, 0x000026, 0x000031, 0x00003B, 0x000046, 0x14554B, 0x28AA50 }; +CRGBPalette16 pacifica_palette_2 = + { 0x000507, 0x000409, 0x00030B, 0x00030D, 0x000210, 0x000212, 0x000114, 0x000117, + 0x000019, 0x00001C, 0x000026, 0x000031, 0x00003B, 0x000046, 0x0C5F52, 0x19BE5F }; +CRGBPalette16 pacifica_palette_3 = + { 0x000208, 0x00030E, 0x000514, 0x00061A, 0x000820, 0x000927, 0x000B2D, 0x000C33, + 0x000E39, 0x001040, 0x001450, 0x001860, 0x001C70, 0x002080, 0x1040BF, 0x2060FF }; + +// Add one layer of waves into the led array +void pacifica_one_layer( CRGBPalette16& p, uint16_t cistart, uint16_t wavescale, uint8_t bri, uint16_t ioff, bool useFibonacciOrder) +{ + uint16_t ci = cistart; + uint16_t waveangle = ioff; + uint16_t wavescale_half = (wavescale / 2) + 20; + for( uint16_t i = 0; i < NUM_PIXELS; i++) { + waveangle += 250; + uint16_t s16 = sin16( waveangle ) + 32768; + uint16_t cs = scale16( s16 , wavescale_half ) + wavescale_half; + ci += cs; + uint16_t sindex16 = sin16( ci) + 32768; + uint8_t sindex8 = scale16( sindex16, 240); + CRGB c = ColorFromPalette( p, sindex8, bri, LINEARBLEND); +#if IS_FIBONACCI + uint16_t idx = useFibonacciOrder ? physicalToFibonacci[i] : i; +#else + (void)useFibonacciOrder; // unused parameter + uint16_t idx = i; +#endif + leds[idx] += c; + } +} + +// Add extra 'white' to areas where the four layers of light have lined up brightly +void pacifica_add_whitecaps(bool useFibonacciOrder) +{ + uint8_t basethreshold = beatsin8( 9, 55, 65); + uint8_t wave = beat8( 7 ); + + for( uint16_t i = 0; i < NUM_PIXELS; i++) { +#if IS_FIBONACCI + uint16_t idx = useFibonacciOrder ? physicalToFibonacci[i] : i; +#else + (void)useFibonacciOrder; // unused parameter + uint16_t idx = i; +#endif + + uint8_t threshold = scale8( sin8( wave), 20) + basethreshold; + wave += 7; + uint8_t l = leds[idx].getAverageLight(); + if( l > threshold) { + uint8_t overage = l - threshold; + uint8_t overage2 = qadd8( overage, overage); + leds[idx] += CRGB( overage, overage2, qadd8( overage2, overage2)); + } + } +} + +// Deepen the blues and greens +void pacifica_deepen_colors(bool useFibonacciOrder) +{ + for( uint16_t i = 0; i < NUM_PIXELS; i++) { +#if IS_FIBONACCI + uint16_t idx = useFibonacciOrder ? physicalToFibonacci[i] : i; +#else + (void)useFibonacciOrder; // unused parameter + uint16_t idx = i; +#endif + + leds[idx].blue = scale8( leds[idx].blue, 145); + leds[idx].green= scale8( leds[idx].green, 200); + leds[idx] |= CRGB( 2, 5, 7); + } +} + +void pacifica_loop_impl(bool useFibonacciOrder) +{ + // Increment the four "color index start" counters, one for each wave layer. + // Each is incremented at a different speed, and the speeds vary over time. + static uint16_t sCIStart1, sCIStart2, sCIStart3, sCIStart4; + static uint32_t sLastms = 0; + uint32_t ms = GET_MILLIS(); + uint32_t deltams = ms - sLastms; + sLastms = ms; + uint16_t speedfactor1 = beatsin16(3, 179, 269); + uint16_t speedfactor2 = beatsin16(4, 179, 269); + uint32_t deltams1 = (deltams * speedfactor1) / 256; + uint32_t deltams2 = (deltams * speedfactor2) / 256; + uint32_t deltams21 = (deltams1 + deltams2) / 2; + sCIStart1 += (deltams1 * beatsin88(1011,10,13)); + sCIStart2 -= (deltams21 * beatsin88(777,8,11)); + sCIStart3 -= (deltams1 * beatsin88(501,5,7)); + sCIStart4 -= (deltams2 * beatsin88(257,4,6)); + + // Clear out the LED array to a dim background blue-green + fill_solid( leds, NUM_PIXELS, CRGB( 2, 6, 10)); + + // Render each of four layers, with different scales and speeds, that vary over time + pacifica_one_layer( pacifica_palette_1, sCIStart1, beatsin16( 3, 11 * 256, 14 * 256), beatsin8( 10, 70, 130), 0-beat16( 301), useFibonacciOrder ); + pacifica_one_layer( pacifica_palette_2, sCIStart2, beatsin16( 4, 6 * 256, 9 * 256), beatsin8( 17, 40, 80), beat16( 401), useFibonacciOrder ); + pacifica_one_layer( pacifica_palette_3, sCIStart3, 6 * 256, beatsin8( 9, 10, 38), 0-beat16(503), useFibonacciOrder ); + pacifica_one_layer( pacifica_palette_3, sCIStart4, 5 * 256, beatsin8( 8, 10, 28), beat16(601), useFibonacciOrder ); + + // Add brighter 'whitecaps' where the waves lines up more + pacifica_add_whitecaps(useFibonacciOrder); + + // Deepen the blues and greens a bit + pacifica_deepen_colors(useFibonacciOrder); +} + +// TODO: Export only these two functions via header file +void pacifica_loop() +{ + return pacifica_loop_impl(false); +} + +#if IS_FIBONACCI +void pacifica_fibonacci_loop() +{ + return pacifica_loop_impl(true); +} +#endif + diff --git a/esp8266-fastled-webserver/PridePlayground.h b/esp8266-fastled-webserver/PridePlayground.h index 609cf665..c58f67e7 100644 --- a/esp8266-fastled-webserver/PridePlayground.h +++ b/esp8266-fastled-webserver/PridePlayground.h @@ -28,7 +28,7 @@ uint8_t sHueBpm = 2; uint8_t sHueMin = 5; uint8_t sHueMax = 9; -void pridePlayground() +void fillWithPridePlayground(bool useFibonacciOrder) { static uint16_t sPseudotime = 0; static uint16_t sLastMillis = 0; @@ -51,7 +51,7 @@ void pridePlayground() sHue16 += deltams * beatsin88(sHueBpm * 256, sHueMin, sHueMax); 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; @@ -66,9 +66,24 @@ void pridePlayground() CRGB newcolor = CHSV(hue8, sat8, bri8); uint16_t pixelnumber = i; +#if IS_FIBONACCI + if (useFibonacciOrder) pixelnumber = fibonacciToPhysical[i]; +#else + (void)useFibonacciOrder; +#endif - pixelnumber = (NUM_LEDS - 1) - pixelnumber; + pixelnumber = (NUM_PIXELS - 1) - pixelnumber; nblend(leds[pixelnumber], newcolor, 64); } } + +void pridePlayground() { + fillWithPridePlayground(false); +} + +#if IS_FIBONACCI +void pridePlaygroundFibonacci() { + fillWithPridePlayground(true); +} +#endif diff --git a/esp8266-fastled-webserver/TwinkleFOX.h b/esp8266-fastled-webserver/TwinkleFOX.h index f920910c..26958890 100644 --- a/esp8266-fastled-webserver/TwinkleFOX.h +++ b/esp8266-fastled-webserver/TwinkleFOX.h @@ -194,7 +194,7 @@ void drawTwinkles() uint8_t backgroundBrightness = bg.getAverageLight(); - for(uint16_t i = 0; i < NUM_LEDS; i++) { + for(uint16_t i = 0; i < NUM_PIXELS; i++) { CRGB& pixel = leds[i]; PRNG16 = (uint16_t)(PRNG16 * 2053) + 1384; // next 'random' number diff --git a/esp8266-fastled-webserver/Twinkles.h b/esp8266-fastled-webserver/Twinkles.h index bcc5d6ae..57efcb74 100644 --- a/esp8266-fastled-webserver/Twinkles.h +++ b/esp8266-fastled-webserver/Twinkles.h @@ -26,7 +26,7 @@ CRGB makeDarker( const CRGB& color, fract8 howMuchDarker) // per pixel. This requires a bunch of bit wrangling, // but conserves precious RAM. The cost is a few // cycles and about 100 bytes of flash program memory. -uint8_t directionFlags[ (NUM_LEDS + 7) / 8]; +uint8_t directionFlags[ (NUM_PIXELS + 7) / 8]; bool getPixelDirection( uint16_t i) { @@ -53,7 +53,7 @@ void setPixelDirection( uint16_t i, bool dir) void brightenOrDarkenEachPixel( fract8 fadeUpAmount, fract8 fadeDownAmount) { - for ( uint16_t i = 0; i < NUM_LEDS; i++) { + for ( uint16_t i = 0; i < NUM_PIXELS; i++) { if ( getPixelDirection(i) == GETTING_DARKER) { // This pixel is getting darker leds[i] = makeDarker( leds[i], fadeDownAmount); @@ -79,7 +79,7 @@ void colortwinkles() // Now consider adding a new random twinkle if ( random8() < DENSITY ) { - int pos = random16(NUM_LEDS); + int pos = random16(NUM_PIXELS); if ( !leds[pos]) { leds[pos] = ColorFromPalette( gCurrentPalette, random8(), STARTING_BRIGHTNESS, NOBLEND); setPixelDirection(pos, GETTING_BRIGHTER); diff --git a/esp8266-fastled-webserver/common.h b/esp8266-fastled-webserver/common.h new file mode 100644 index 00000000..bae126c2 --- /dev/null +++ b/esp8266-fastled-webserver/common.h @@ -0,0 +1,107 @@ +/* + 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 . +*/ + +#if !defined(ESP8266_FASTLED_WEBSERVER_COMMON_H) +#define ESP8266_FASTLED_WEBSERVER_COMMON_H + +#include "./include/simplehacks/static_eval.h" +#include "./include/simplehacks/constexpr_strlen.h" +#include "./include/simplehacks/array_size2.h" +#include "config.h" // must be included before FastLED.h + +#define FASTLED_INTERNAL // no other way to suppress build warnings +#include +FASTLED_USING_NAMESPACE + +extern "C" { +#include "user_interface.h" +} + +#include +#define MYFS LittleFS + +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include // https://github.com/tzapu/WiFiManager/tree/development + +#if defined(ENABLE_IR) + #include +#endif + +// forward-declarations +// Only list those variables that are needed by the local +// project "header" files (the ones that are actually C++ files) +extern const TProgmemRGBGradientPalettePtr gGradientPalettes[]; +extern const uint8_t gGradientPaletteCount; +extern const CRGBPalette16 palettes[]; +extern const uint8_t paletteCount; +extern const String paletteNames[]; + +extern WiFiManager wifiManager; +extern ESP8266WebServer webServer; +extern String nameString; + + +#if IS_FIBONACCI + extern const uint16_t physicalToFibonacci [NUM_PIXELS]; + extern const uint16_t fibonacciToPhysical [NUM_PIXELS]; + extern const uint8_t coordsX[NUM_PIXELS]; + extern const uint8_t coordsY[NUM_PIXELS]; + extern const uint8_t angles[NUM_PIXELS]; +#endif + +// Structures +typedef void (*Pattern)(); +typedef Pattern PatternList[]; +typedef struct { + Pattern pattern; + String name; +} PatternAndName; +typedef PatternAndName PatternAndNameList[]; + +typedef struct { + CRGBPalette16 palette; + String name; +} PaletteAndName; +typedef PaletteAndName PaletteAndNameList[]; + + + +// Function prototypes + +// Local C++ sources that are masquerading as header files +#include "GradientPalettes.h" +#include "Info.h" +#include "Field.h" +#include "FSBrowser.h" +#include "Ping.h" + +#if defined(ENABLE_IR) + #include "Commands.h" +#endif + + + +#endif // ESP8266_FASTLED_WEBSERVER_COMMON_H diff --git a/esp8266-fastled-webserver/config.h b/esp8266-fastled-webserver/config.h new file mode 100644 index 00000000..ae4ee241 --- /dev/null +++ b/esp8266-fastled-webserver/config.h @@ -0,0 +1,130 @@ +/* + 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 . +*/ + +#if !defined(ESP8266_FASTLED_WEBSERVER_CONFIG_H) +#define ESP8266_FASTLED_WEBSERVER_CONFIG_H + + +// This header file lists (and provides defaults for) the various configurations. +// When compiling from Arduino, you can edit this file. +// When compiling from PlatformIO, this is a reference for compiler flags + +//#define PRODUCT_DEFAULT +#define PRODUCT_FIBONACCI256 + +// //////////////////////////////////////////////////////////////////////////////////////////////////// +// Additional configuration options ... defaults shown +// //////////////////////////////////////////////////////////////////////////////////////////////////// +// #define UTC_OFFSET_IN_SECONDS (-6L * 60L * 60L) // UTC-6 (East-coast US ... no DST support) +// #define NTP_UPDATE_THROTTLE_MILLLISECONDS (5UL * 60UL * 60UL * 1000UL) // Ping NTP server no more than every 5 minutes +// +// TODO: add option to disable NTP altogether + +// //////////////////////////////////////////////////////////////////////////////////////////////////// +// Include the configuration files for this build +// //////////////////////////////////////////////////////////////////////////////////////////////////// +#if 1 + // Product-specific configuration + #if defined(PRODUCT_DEFAULT) + #include "include\configs\product\default.h" + #elif defined(PRODUCT_FIBONACCI256) + #include "include\configs\product\fibonacci256.h" + #else + #error "Must define product to build against" + #endif + + // Board-specific configuration + #if defined(ARDUINO_ARCH_ESP32) + #include "include\configs\controller\controller_esp32.h" + #else + #include "include\configs\controller\controller_esp8266.h" + #endif +#endif + + +// //////////////////////////////////////////////////////////////////////////////////////////////////// +// Set defaults for optional values +// //////////////////////////////////////////////////////////////////////////////////////////////////// +#if 1 + #if !defined(UTC_OFFSET_IN_SECONDS) + #define UTC_OFFSET_IN_SECONDS (-6L * 60L * 60L) // UTC-6 (East-coast US ... no DST support) + #endif + #if !defined(NTP_UPDATE_THROTTLE_MILLLISECONDS) + #define NTP_UPDATE_THROTTLE_MILLLISECONDS (5UL * 60UL * 60UL * 1000UL) // Ping NTP server no more than every 5 minutes + #endif +#endif + +// //////////////////////////////////////////////////////////////////////////////////////////////////// +// Validate configuration options +// //////////////////////////////////////////////////////////////////////////////////////////////////// + +#if 1 + #if !defined(LED_TYPE) + #error "LED_TYPE must be defined by product" + #endif + #if !defined(COLOR_ORDER) + #error "COLOR_ORDER must be defined by product" + #endif + #if !defined(NUM_PIXELS) + #error "NUM_PIXELS must be defined by product" + #endif + #if !defined(AVAILABLE_MILLI_AMPS) + #error "AVAILABLE_MILLI_AMPS must be defined by product" + #endif + #if !defined(MAX_MILLI_AMPS_PER_PIXEL) + #error "MAX_MILLI_AMPS_PER_PIXEL must be defined by product" + #endif + #if !defined(FRAMES_PER_SECOND) + #error "FRAMES_PER_SECOND must be defined by product" + #endif + #if !defined(DEFAULT_PATTERN_INDEX) + #error "DEFAULT_PATTERN_INDEX must be defined by product" + #endif + #if !defined(DEFAULT_COLOR_CORRECTION) + #error "DEFAULT_COLOR_CORRECTION must be defined by product" + #endif + #if defined(ENABLE_IR) && !defined(IR_RECV_PIN) + #error "IR_RECV_PIN must be defined by product when ENABLE_IR is defined" + #endif + #if !defined(NAME_PREFIX) + #error "NAME_PREFIX must be defined by product" + #endif + #if !defined(PRODUCT_FRIENDLY_NAME) + #error "PRODUCT_FRIENDLY_NAME must be defined by product" + #endif + // IS_FIBONACCI: There does not appear to be a way to check, at compile-time here, if requirements are met + #if (UTC_OFFSET_IN_SECONDS < (-14L * 60L * 60L)) + #error "UTC_OFFSET_IN_SECONDS offset does not appear correct (< -14H) ... Note it is defined in seconds." + #elif (UTC_OFFSET_IN_SECONDS > (14L * 60L * 60L)) + #error "UTC_OFFSET_IN_SECONDS offset does not appear correct (> +14H) ... Note it is defined in seconds." + #endif + #if (NTP_UPDATE_THROTTLE_MILLLISECONDS < (15UL * 1000UL)) + #error "NTP_UPDATE_THROTTLE_MILLLISECONDS less than 15 seconds ... may exceed rate limits" + #endif + +#endif + + + +#if defined(MILLI_AMPS) + #error "Legacy symbol MILLI_AMPS should be changed to AVAILABLE_MILLI_AMPS" +#endif +#define MAX_MILLI_AMPS (MAX_MILLI_AMPS_PER_PIXEL * NUM_PIXELS) + + +#endif // ESP8266_FASTLED_WEBSERVER_CONFIG_H diff --git a/esp8266-fastled-webserver/data/index.htm b/esp8266-fastled-webserver/data/index.htm index c3c5d531..8ac79725 100644 --- a/esp8266-fastled-webserver/data/index.htm +++ b/esp8266-fastled-webserver/data/index.htm @@ -5,7 +5,7 @@ - ESP8266 + FastLED by Evil Genius Labs +   @@ -36,8 +36,9 @@
diff --git a/esp8266-fastled-webserver/data/js/app.js b/esp8266-fastled-webserver/data/js/app.js index 814efbda..02cba8be 100644 --- a/esp8266-fastled-webserver/data/js/app.js +++ b/esp8266-fastled-webserver/data/js/app.js @@ -470,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/esp8266-fastled-webserver.ino b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino index 3d4a045f..52527e29 100644 --- a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino +++ b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino @@ -44,7 +44,7 @@ CRGB leds[NUM_PIXELS]; const uint8_t brightnessCount = 5; uint8_t brightnessMap[brightnessCount] = { 16, 32, 64, 128, 255 }; -uint8_t brightnessIndex = 3; +uint8_t brightnessIndex = DEFAULT_BRIGHTNESS_INDEX; // ten seconds per color palette makes a good demo // 20-120 is better for deployment @@ -245,11 +245,53 @@ const String paletteNames[paletteCount] = { #include "Fields.h" -// TODO / BUGBUG -- should this be ESP8266-specific? +// 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 +// Ugly macro-like constexpr, used for FastLED template arguments +template +constexpr int LedOffset() { + static_assert(ONE_BASED_OUTPUT_CHANNEL <= PARALLEL_OUTPUT_CHANNELS, ""); + static_assert(ONE_BASED_OUTPUT_CHANNEL >= 1, ""); + return 0 // this would be much simpler with C++14 + #if PARALLEL_OUTPUT_CHANNELS >= 2 + + ((ONE_BASED_OUTPUT_CHANNEL >= 2) ? PIXELS_ON_DATA_PIN_1 : 0) + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 3 + + ((ONE_BASED_OUTPUT_CHANNEL >= 3) ? PIXELS_ON_DATA_PIN_2 : 0) + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 4 + + ((ONE_BASED_OUTPUT_CHANNEL >= 4) ? PIXELS_ON_DATA_PIN_3 : 0) + #endif + ; +} +template +constexpr int LedCount() { + static_assert(ONE_BASED_OUTPUT_CHANNEL <= PARALLEL_OUTPUT_CHANNELS, ""); + static_assert(ONE_BASED_OUTPUT_CHANNEL >= 1, ""); + #if PARALLEL_OUTPUT_CHANNELS == 1 + return NUM_PIXELS; + #else + return // this would be much simpler with C++14 + #if PARALLEL_OUTPUT_CHANNELS >= 4 + (ONE_BASED_OUTPUT_CHANNEL == 4) ? PIXELS_ON_DATA_PIN_4 : + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 3 + (ONE_BASED_OUTPUT_CHANNEL == 3) ? PIXELS_ON_DATA_PIN_3 : + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 2 + (ONE_BASED_OUTPUT_CHANNEL == 2) ? PIXELS_ON_DATA_PIN_2 : + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 1 + (ONE_BASED_OUTPUT_CHANNEL == 1) ? PIXELS_ON_DATA_PIN_1 : + #endif + 0; + #endif +} + void setup() { WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP @@ -260,8 +302,23 @@ void setup() { 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 + #endif // PARALLEL_OUTPUT_CHANNELS + //FastLED.addLeds(leds, NUM_PIXELS); // for APA102 (Dotstar) + FastLED.setDither(false); FastLED.setCorrection(TypicalLEDStrip); FastLED.setBrightness(brightness); @@ -274,7 +331,9 @@ void setup() { 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:")); @@ -939,9 +998,60 @@ void loop() { // TODO: Save settings in file system, not EEPROM! + // TODO: Combine settings for all builds into a single structure. + // TODO: Update magic number from 0x55 to 0xAA (or 0x96 or 0x69) +void readSettingsFib128() +{ + // 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) { + return; + } + + brightness = EEPROM.read(0); + + currentPatternIndex = EEPROM.read(1); + if (currentPatternIndex >= patternCount) { + currentPatternIndex = patternCount - 1; + } + + byte r = EEPROM.read(2); + byte g = EEPROM.read(3); + byte b = EEPROM.read(4); + + if (r == 0 && g == 0 && b == 0) + { + } + else + { + solidColor = CRGB(r, g, b); + } + + power = EEPROM.read(5); + + autoplay = EEPROM.read(6); + autoplayDuration = EEPROM.read(7); + + currentPaletteIndex = EEPROM.read(8); + if (currentPaletteIndex >= paletteCount) { + currentPaletteIndex = paletteCount - 1; + } + + twinkleSpeed = EEPROM.read(9); + twinkleDensity = EEPROM.read(10); + + cooling = EEPROM.read(11); + sparking = EEPROM.read(12); + + coolLikeIncandescent = EEPROM.read(13); + + showClock = EEPROM.read(14); + clockBackgroundFade = EEPROM.read(15); +} void readSettingsFib256() { // check for "magic number" so we know settings have been written to EEPROM @@ -990,7 +1100,54 @@ void readSettingsFib256() // coolLikeIncandescent = EEPROM.read(13); } +void readSettingsFib512() +{ + // 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) { + return; + } + + brightness = EEPROM.read(0); + + currentPatternIndex = EEPROM.read(1); + if (currentPatternIndex >= patternCount) { + currentPatternIndex = patternCount - 1; + } + + byte r = EEPROM.read(2); + byte g = EEPROM.read(3); + byte b = EEPROM.read(4); + + if (r == 0 && g == 0 && b == 0) + { + } + else + { + solidColor = CRGB(r, g, b); + } + + power = EEPROM.read(5); + + autoplay = EEPROM.read(6); + autoplayDuration = EEPROM.read(7); + + currentPaletteIndex = EEPROM.read(8); + if (currentPaletteIndex >= paletteCount) { + currentPaletteIndex = paletteCount - 1; + } + twinkleSpeed = EEPROM.read(9); + twinkleDensity = EEPROM.read(10); + + cooling = EEPROM.read(11); + sparking = EEPROM.read(12); + + coolLikeIncandescent = EEPROM.read(13); + + showClock = EEPROM.read(14); + clockBackgroundFade = EEPROM.read(15); +} void readSettingsDefaultProduct() { // check for "magic number" so we know settings have been written to EEPROM @@ -1039,8 +1196,12 @@ void readSettingsDefaultProduct() } void readSettings() { - #if defined(PRODUCT_FIBONACCI256) + #if defined(PRODUCT_FIBONACCI512) + readSettingsFib512(); + #elif defined(PRODUCT_FIBONACCI256) readSettingsFib256(); + #elif defined(PRODUCT_FIBONACCI128) + readSettingsFib128(); #elif defined(PRODUCT_DEFAULT) readSettingsDefaultProduct(); #else @@ -1048,6 +1209,27 @@ void readSettings() { #endif } +void writeAndCommitSettingsFib128() +{ + EEPROM.write(0, brightness); + EEPROM.write(1, currentPatternIndex); + EEPROM.write(2, solidColor.r); + EEPROM.write(3, solidColor.g); + EEPROM.write(4, solidColor.b); + EEPROM.write(5, power); + EEPROM.write(6, autoplay); + EEPROM.write(7, autoplayDuration); + EEPROM.write(8, currentPaletteIndex); + EEPROM.write(9, twinkleSpeed); + EEPROM.write(10, twinkleDensity); + EEPROM.write(11, cooling); + EEPROM.write(12, sparking); + EEPROM.write(13, coolLikeIncandescent); + EEPROM.write(14, showClock); + EEPROM.write(15, clockBackgroundFade); + EEPROM.write(511, 55); + EEPROM.commit(); +} void writeAndCommitSettingsFib256() { EEPROM.write(0, brightness); @@ -1064,6 +1246,28 @@ void writeAndCommitSettingsFib256() EEPROM.write(511, 55); EEPROM.commit(); } +void writeAndCommitSettingsFib512() +{ + EEPROM.write(0, brightness); + EEPROM.write(1, currentPatternIndex); + EEPROM.write(2, solidColor.r); + EEPROM.write(3, solidColor.g); + EEPROM.write(4, solidColor.b); + EEPROM.write(5, power); + EEPROM.write(6, autoplay); + EEPROM.write(7, autoplayDuration); + EEPROM.write(8, currentPaletteIndex); + EEPROM.write(9, twinkleSpeed); + EEPROM.write(10, twinkleDensity); + EEPROM.write(11, cooling); + EEPROM.write(12, sparking); + EEPROM.write(13, coolLikeIncandescent); + EEPROM.write(14, showClock); + EEPROM.write(15, clockBackgroundFade); + EEPROM.write(511, 55); + EEPROM.commit(); +} + void writeAndCommitSettingsDefaultProduct() { EEPROM.write(0, brightness); @@ -1084,11 +1288,14 @@ void writeAndCommitSettingsDefaultProduct() EEPROM.commit(); } - void writeAndCommitSettings() { - #if defined(PRODUCT_FIBONACCI256) + #if defined(PRODUCT_FIBONACCI512) + writeAndCommitSettingsFib512(); + #elif defined(PRODUCT_FIBONACCI256) writeAndCommitSettingsFib256(); + #elif defined(PRODUCT_FIBONACCI128) + writeAndCommitSettingsFib128(); #elif defined(PRODUCT_DEFAULT) writeAndCommitSettingsDefaultProduct(); #else @@ -1392,10 +1599,11 @@ void fillWithPride(bool useFibonacciOrder) void pride() { fillWithPride(false); } +#if IS_FIBONACCI // prideFibonacci() uses fibonacciToPhysical void prideFibonacci() { fillWithPride(true); } - +#endif void fillRadialPaletteShift(bool useFibonacciOrder) { @@ -1403,6 +1611,7 @@ void fillRadialPaletteShift(bool useFibonacciOrder) #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); @@ -1414,6 +1623,7 @@ void fillRadialPaletteShiftOutward(bool useFibonacciOrder) #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); @@ -1569,7 +1779,7 @@ void colorWaves() { fillWithColorwaves( leds, NUM_PIXELS, gCurrentPalette, false); } -#if IS_FIBONACCI +#if IS_FIBONACCI // colorWavesFibonacci() uses fibonacciToPhysical void colorWavesFibonacci() { fillWithColorwaves( leds, NUM_PIXELS, gCurrentPalette, true); @@ -1586,7 +1796,7 @@ void palettetest( CRGB* ledarray, uint16_t numleds, const CRGBPalette16& gCurren } -#if IS_FIBONACCI // uses physicalToFibonacci and angles +#if IS_FIBONACCI // swirlFibonacci() uses physicalToFibonacci and angles void swirlFibonacci() { const float z = 2.5; // zoom (2.0) @@ -1617,7 +1827,7 @@ void swirlFibonacci() { } #endif -#if IS_FIBONACCI // uses coordsX/coordsY +#if IS_FIBONACCI // fireFibonacci() uses coordsX/coordsY // TODO: combine with normal fire effect void fireFibonacci() { for (uint16_t i = 0; i < NUM_PIXELS; i++) { @@ -1631,7 +1841,7 @@ void fireFibonacci() { } #endif -#if IS_FIBONACCI // uses coordsX/coordsY +#if IS_FIBONACCI // waterFibonacci() uses coordsX/coordsY // TODO: combine with normal water effect void waterFibonacci() { for (uint16_t i = 0; i < NUM_PIXELS; i++) { @@ -1645,7 +1855,7 @@ void waterFibonacci() { } #endif -#if IS_FIBONACCI // uses angle, antialiasPixelAR() +#if IS_FIBONACCI // emitterFibonacci() uses angle, antialiasPixelAR() /** * Emits arcs of color spreading out from the center to the edge of the disc. */ diff --git a/esp8266-fastled-webserver/include/configs/controller/controller_esp32.h b/esp8266-fastled-webserver/include/configs/controller/controller_esp32.h index ce3247e7..5810fa24 100644 --- a/esp8266-fastled-webserver/include/configs/controller/controller_esp32.h +++ b/esp8266-fastled-webserver/include/configs/controller/controller_esp32.h @@ -20,7 +20,32 @@ #if !defined(ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP32_H) #define ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP32_H -#define DATA_PIN 18 // d1 mini32 (same physical location as D5 on the d1 mini) + +static_assert(PARALLEL_OUTPUT_CHANNELS <= 4, "ESP32 only has support for four parallel outputs defined, can be updated to support 16 outputs"); + + + +#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) diff --git a/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h b/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h index ec492644..74f8e050 100644 --- a/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h +++ b/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h @@ -20,7 +20,25 @@ #if !defined(ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP8266_H) #define ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP8266_H -#define DATA_PIN D5 // d1 mini +static_assert(PARALLEL_OUTPUT_CHANNELS <= 4, "ESP8266 only supports four 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(ENABLE_IR) && !defined(IR_RECV_PIN) #define IR_RECV_PIN D4 diff --git a/esp8266-fastled-webserver/include/configs/product/default.h b/esp8266-fastled-webserver/include/configs/product/default.h index 75f0099b..cb81478d 100644 --- a/esp8266-fastled-webserver/include/configs/product/default.h +++ b/esp8266-fastled-webserver/include/configs/product/default.h @@ -20,16 +20,47 @@ #if !defined(ESP8266_FASTLED_WEBSERVER_PRODUCT_DEFAULT_H) #define ESP8266_FASTLED_WEBSERVER_PRODUCT_DEFAULT_H -#define LED_TYPE WS2811 -#define COLOR_ORDER RGB -#define NUM_PIXELS 200 -#define AVAILABLE_MILLI_AMPS 2000 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA) -#define MAX_MILLI_AMPS_PER_PIXEL 60 // IMPORTANT: set to larger value if necessary -#define FRAMES_PER_SECOND 120 -#define DEFAULT_PATTERN_INDEX 0 -#define DEFAULT_COLOR_CORRECTION TypicalLEDStrip -#define NAME_PREFIX "ESP8266-" -#define PRODUCT_FRIENDLY_NAME "ESP8266 + FastLED" -#define IS_FIBONACCI 0 +#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(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/fibonacci128.h b/esp8266-fastled-webserver/include/configs/product/fibonacci128.h new file mode 100644 index 00000000..b366b288 --- /dev/null +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci128.h @@ -0,0 +1,64 @@ +/* + 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(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 index 6f489133..aa66389b 100644 --- a/esp8266-fastled-webserver/include/configs/product/fibonacci256.h +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci256.h @@ -20,19 +20,47 @@ #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(PARALLEL_OUTPUT_CHANNELS) + #define PARALLEL_OUTPUT_CHANNELS 1 +#endif -#define LED_TYPE WS2812B -#define COLOR_ORDER GRB -#define NUM_PIXELS 256 -#define AVAILABLE_MILLI_AMPS 1600 // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA) -#define MAX_MILLI_AMPS_PER_PIXEL 12 // IMPORTANT: set to larger value if necessary -#define FRAMES_PER_SECOND 120 -#define DEFAULT_PATTERN_INDEX 3 -#define DEFAULT_COLOR_CORRECTION TypicalSMD5050 -#define NAME_PREFIX "Fibonacci256-" -#define PRODUCT_FRIENDLY_NAME "Fibonacci256" -#define IS_FIBONACCI 1 #endif // ESP8266_FASTLED_WEBSERVER_PRODUCT_FIB256_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..a144a2ca --- /dev/null +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci512.h @@ -0,0 +1,76 @@ +/* + 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(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/product_template.h b/esp8266-fastled-webserver/include/configs/product/product_template.h index adfc284e..d572b864 100644 --- a/esp8266-fastled-webserver/include/configs/product/product_template.h +++ b/esp8266-fastled-webserver/include/configs/product/product_template.h @@ -28,18 +28,36 @@ // LED_TYPE defines the control pattern for the LEDs // See https://github.com/FastLED/FastLED/blob/b5874b588ade1d2639925e4e9719fa7d3c9d9e94/src/FastLED.h#L92-L119 -#define LED_TYPE WS2811 + +#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 -#define COLOR_ORDER RGB +#if !defined(COLOR_ORDER) + #define COLOR_ORDER RGB +#endif // NUM_PIXELS is the number of pixels to be -#define NUM_PIXELS 200 -#error #define AVAILABLE_MILLI_AMPS x2000x // IMPORTANT: set the max milli-Amps of your power supply (4A = 4000mA) -#define MAX_MILLI_AMPS_PER_PIXEL 60 -#define FRAMES_PER_SECOND 120 -#define DEFAULT_PATTERN_INDEX 0 +#if !defined(NUM_PIXELS) + #define NUM_PIXELS 200 +#endif +#if !defined(AVAILABLE_MILLI_AMPS) + #error #define AVAILABLE_MILLI_AMPS x2000x // 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 // DEFAULT_COLOR_CORRECTION defines which FastLED built-in color correction to apply // Options include: @@ -53,15 +71,21 @@ // static_cast(0xRRGGBB) // // See https://github.com/FastLED/FastLED/blob/b5874b588ade1d2639925e4e9719fa7d3c9d9e94/src/color.h#L13-L32 -#define DEFAULT_COLOR_CORRECTION TypicalLEDStrip +#if !defined(DEFAULT_COLOR_CORRECTION) + #define DEFAULT_COLOR_CORRECTION TypicalLEDStrip +#endif // NAME_PREFIX defines the product-specific prefix for auto-generated hostname -#define NAME_PREFIX "ESP8266-" +#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 -#define PRODUCT_FRIENDLY_NAME "ESP8266 + FastLED" +#if !defined(PRODUCT_FRIENDLY_NAME) + #define PRODUCT_FRIENDLY_NAME "ESP8266 + FastLED" +#endif // IS_FIBONACCI is true when there are fibonacci-specific definitions for the product. // TODO: Consider splitting to two variables: @@ -77,11 +101,60 @@ // const uint8_t coordsX[NUM_PIXELS]; // const uint8_t coordsY[NUM_PIXELS]; // const uint8_t angles[NUM_PIXELS]; -#define IS_FIBONACCI 0 +#if !defined(IS_FIBONACCI) + #define IS_FIBONACCI 1 +#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 +// +// Up to the number of parallel outputs, +// *AND* the board file must support the required number of channels +// by defining the corresponding pins as follows: +// +// #define DATA_PIN w +// #define DATA_PIN_2 x +// #define DATA_PIN_3 y +// ... +// #define DATA_PIN_n z +// + +#if !defined(PARALLEL_OUTPUT_CHANNELS) + #define PARALLEL_OUTPUT_CHANNELS 1 +#endif +// Example from Fibonacci512: +// +// #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 // By default, no IR support is included. Define ENABLE_IR to enable IR support. // #define ENABLE_IR // NOTE: When ENABLE_IR is defined, can also override controller-specific default: // #define IR_RECV_PIN D99 + + + #error #endif // ESP8266_FASTLED_WEBSERVER_PRODUCT_xyzz_H From e991afb170c6d3d8c6945cbb8e9e900bf5d38c69 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Fri, 15 Oct 2021 23:04:21 -0700 Subject: [PATCH 03/16] Squashed commit from combined_dev3: * Add support for Fibonacci64 * Add support for Fibonacci64Mini * Add support for Fibonacci32 * Reduce const array sizes in map.h * Remove redundant array 'radii' from map.h --- esp8266-fastled-webserver/Fields.h | 6 + esp8266-fastled-webserver/Map.h | 129 +++++++++++------ esp8266-fastled-webserver/common.h | 23 ++- esp8266-fastled-webserver/config.h | 17 ++- .../esp8266-fastled-webserver.ino | 137 ++++++++++++++++++ .../configs/controller/controller_esp32.h | 6 +- .../include/configs/product/fibonacci32.h | 64 ++++++++ .../include/configs/product/fibonacci64.h | 111 ++++++++++++++ .../configs/product/product_template.h | 7 +- 9 files changed, 449 insertions(+), 51 deletions(-) create mode 100644 esp8266-fastled-webserver/include/configs/product/fibonacci32.h create mode 100644 esp8266-fastled-webserver/include/configs/product/fibonacci64.h diff --git a/esp8266-fastled-webserver/Fields.h b/esp8266-fastled-webserver/Fields.h index 3843a226..3537de73 100644 --- a/esp8266-fastled-webserver/Fields.h +++ b/esp8266-fastled-webserver/Fields.h @@ -37,6 +37,12 @@ String getPower() { // return String(brightness); //} +// TODO: wrapper class for EEPROM settings, to help ensure clear understanding +// of all locations that can cause settings committed / EEPROM write. +// Also simplifies reading prior value before writing new value (extend EEPROM life) +// Also simplifies later extending CRC, transactional updates, bypassing "dead" +// areas of EEPROM, etc. + String getBrightness() { return String(brightness); } diff --git a/esp8266-fastled-webserver/Map.h b/esp8266-fastled-webserver/Map.h index 230e165d..b9231b70 100644 --- a/esp8266-fastled-webserver/Map.h +++ b/esp8266-fastled-webserver/Map.h @@ -2,9 +2,9 @@ // Each Fibonacci board must define the following arrays: // -// physicalToFibonacci[] === physical LED order to ordered by radius (vogel spiral order) -// fibonacciToPhysical[] === radius (vogel spiral order) to physical LED order -// angles[] === angle, where the range is from 0..255 for entire circle +// physicalToFibonacci[] === given physical pixel number, get it's order if sorted by distance from center (radius, aka the vogel spiral order) +// fibonacciToPhysical[] === given index to pixel in radial order (vogel spiral order), get physical pixel index +// angles[] === angle, using units where 256 units == 360 degrees // coordsX[] / coordsY[] === uint8_t coordinates for transformed spiral // // All boards appear to use the vogel model, with offset to first point == 0. @@ -12,22 +12,44 @@ // i.e., the first point is the center of the spiral at origin (x=0, y=0) // ]] // -// Once all the LEDs actual positions are calculated, transform the original -// coordinates to fit the uint8_t coordinates used: +// 1. Using radial coordinates, the Nth pixel's position is defined as: +// ``` +// r = sqrt(n) +// theta = n * GOLDEN_ANGLE +// ``` // -// 1. Translate the spiral so minimum X value is zero (shift right) -// 2. Translate the spiral so minimum Y value is zero (shift up) -// 3. Scale the resulting spiral so maximum X / Y value is 255. -// -// The resulting coordinates are then stored in the coordsX/Y ranges, -// to allow for faster (8-bit) math operations on lower-power MCUs. +// 2. Calculate all coordinates, giving Vogel's model centered at the origin +// +// 3. Store theta in `angles[]` (after converting to units where 256 units == 360 degrees) +// +// 4. Convert the radial coordinates to cartesian (x/y) coordinates +// +// 5. Transform the coordinates, such as via following psuedo-code: +// +// ```C++ +// // first, translate from origin == center so left side and bottom aligned with X/Y axis +// double shiftX := min(originalCoordinatesX[]); +// double shiftY := min(originalCoordinatesY[]); +// double translatedX[] <== originalCoordinatesX[] - shiftX; // shifts right to align left side with X=0 +// double translatedY[] = originalCoordinatesY[] - shiftY; // shifts upward to align bottom with Y=0 +// // next, scale so that values lie entirely within the range [ 0.0 ... 256.0 ] +// double maxXY = max(max(translatedX[]), max(translatedY[]); +// double scaleFactor = 256.0 / maxXY; +// double scaledX[] = translatedX[] * scaleFactor; +// double scaledY[] = translatedY[] * scaleFactor; +// // finally, convert to integer values in the range [ 0 ... 255 ] +// uint8_t coordsX[] = (uint8_t)(scaledX[] - 0.5); // subtract 0.5 to avoid bias +// uint8_t coordsY[] = (uint8_t)(scaledY[] - 0.5); // subtract 0.5 to avoid bias +// ``` +// +// There appears to have been a concious decision to store the X/Y +// values as 8-bit values. Perhaps this was to allow for faster +// (8-bit) math operations on lower-power MCUs? +// +// Of course, the supported boards are ESP8266 or ESP32 (or SAMD21E), +// each of which are 32-bit native processors. If this was on AVR, +// the continued use of 8-bit algorithms would be more critical. // - -// TODO: only Fib256/Fib512 need first two arrays to be uint16_t -// consider defining as uint8_t vs. uint16_t, and updating -// dependent code to infer type at compilation time? This -// may save a few cycles on the QT Py and similar MCUs.... -// For now, just upgrading them all to use `uint16_t`... #if defined(PRODUCT_FIBONACCI512) const uint16_t physicalToFibonacci[NUM_PIXELS] { 510, 476, 442, 408, 374, 340, 306, 272, 238, 204, 170, 136, 102, 68, 34, 0, 13, 47, 81, 115, 149, 183, 217, 251, 285, 319, 353, 387, 421, 455, 489, 502, 468, 434, 400, 366, 332, 298, 264, 230, 196, 162, 128, 94, 60, 26, 5, 39, 73, 107, 141, 175, 209, 243, 277, 311, 345, 379, 413, 447, 481, 494, 460, 426, 392, 358, 324, 290, 256, 222, 188, 154, 120, 86, 52, 18, 31, 65, 99, 133, 167, 201, 235, 269, 303, 337, 371, 405, 439, 473, 507, 486, 452, 418, 384, 350, 316, 282, 248, 214, 180, 146, 112, 78, 44, 10, 23, 57, 91, 125, 159, 193, 227, 261, 295, 329, 363, 397, 431, 465, 499, 478, 444, 410, 376, 342, 308, 274, 240, 206, 172, 138, 104, 70, 36, 2, 15, 49, 83, 117, 151, 185, 219, 253, 287, 321, 355, 389, 423, 457, 491, 504, 470, 436, 402, 368, 334, 300, 266, 232, 198, 164, 130, 96, 62, 28, 7, 41, 75, 109, 143, 177, 211, 245, 279, 313, 347, 381, 415, 449, 483, 496, 462, 428, 394, 360, 326, 292, 258, 224, 190, 156, 122, 88, 54, 20, 33, 67, 101, 135, 169, 203, 237, 271, 305, 339, 373, 407, 441, 475, 509, 488, 454, 420, 386, 352, 318, 284, 250, 216, 182, 148, 114, 80, 46, 12, 25, 59, 93, 127, 161, 195, 229, 263, 297, 331, 365, 399, 433, 467, 501, 480, 446, 412, 378, 344, 310, 276, 242, 208, 174, 140, 106, 72, 38, 4, 17, 51, 85, 119, 153, 187, 221, 255, 289, 323, 357, 391, 425, 459, 493, 506, 472, 438, 404, 370, 336, 302, 268, 234, 200, 166, 132, 98, 64, 30, 9, 43, 77, 111, 145, 179, 213, 247, 281, 315, 349, 383, 417, 451, 485, 498, 464, 430, 396, 362, 328, 294, 260, 226, 192, 158, 124, 90, 56, 22, 1, 35, 69, 103, 137, 171, 205, 239, 273, 307, 341, 375, 409, 443, 477, 511, 490, 456, 422, 388, 354, 320, 286, 252, 218, 184, 150, 116, 82, 48, 14, 27, 61, 95, 129, 163, 197, 231, 265, 299, 333, 367, 401, 435, 469, 503, 482, 448, 414, 380, 346, 312, 278, 244, 210, 176, 142, 108, 74, 40, 6, 19, 53, 87, 121, 155, 189, 223, 257, 291, 325, 359, 393, 427, 461, 495, 508, 474, 440, 406, 372, 338, 304, 270, 236, 202, 168, 134, 100, 66, 32, 11, 45, 79, 113, 147, 181, 215, 249, 283, 317, 351, 385, 419, 453, 487, 500, 466, 432, 398, 364, 330, 296, 262, 228, 194, 160, 126, 92, 58, 24, 3, 37, 71, 105, 139, 173, 207, 241, 275, 309, 343, 377, 411, 445, 479, 492, 458, 424, 390, 356, 322, 288, 254, 220, 186, 152, 118, 84, 50, 16, 29, 63, 97, 131, 165, 199, 233, 267, 301, 335, 369, 403, 437, 471, 505, 484, 450, 416, 382, 348, 314, 280, 246, 212, 178, 144, 110, 76, 42, 8, 21, 55, 89, 123, 157, 191, 225, 259, 293, 327, 361, 395, 429, 463, 497 }; @@ -35,25 +57,30 @@ const uint8_t coordsX[NUM_PIXELS] { 170, 178, 185, 191, 196, 199, 202, 202, 202, 200, 196, 191, 184, 175, 161, 132, 148, 166, 176, 183, 188, 190, 192, 191, 190, 186, 182, 176, 170, 162, 153, 125, 136, 145, 154, 161, 168, 173, 177, 180, 181, 181, 178, 174, 167, 155, 139, 157, 164, 169, 170, 170, 168, 165, 160, 154, 147, 139, 129, 119, 109, 82, 93, 104, 114, 124, 132, 140, 147, 152, 157, 159, 160, 159, 155, 145, 145, 150, 150, 149, 146, 141, 135, 127, 119, 110, 100, 90, 79, 68, 57, 45, 56, 66, 77, 87, 97, 107, 115, 123, 130, 135, 139, 142, 141, 136, 134, 134, 131, 126, 120, 113, 105, 96, 86, 76, 66, 56, 45, 35, 25, 18, 27, 37, 47, 57, 67, 77, 86, 95, 104, 112, 119, 124, 128, 129, 125, 120, 113, 105, 97, 88, 78, 69, 59, 50, 40, 31, 22, 14, 6, 0, 6, 12, 19, 27, 35, 44, 54, 63, 73, 82, 91, 101, 109, 118, 121, 108, 98, 88, 78, 69, 59, 50, 41, 33, 25, 18, 12, 7, 3, 6, 8, 11, 15, 20, 26, 33, 40, 48, 57, 67, 77, 87, 98, 111, 102, 89, 77, 67, 58, 49, 41, 34, 28, 23, 19, 16, 15, 14, 15, 26, 24, 23, 24, 26, 28, 33, 38, 44, 51, 60, 69, 80, 93, 111, 100, 85, 73, 64, 55, 49, 43, 39, 36, 34, 33, 34, 36, 39, 43, 58, 53, 49, 45, 44, 43, 44, 46, 50, 55, 61, 69, 79, 93, 116, 104, 87, 76, 68, 62, 58, 55, 54, 54, 55, 58, 62, 68, 74, 82, 108, 99, 90, 83, 77, 72, 68, 65, 64, 65, 67, 70, 76, 85, 97, 112, 94, 85, 80, 76, 75, 75, 77, 81, 85, 91, 98, 106, 115, 125, 153, 142, 131, 122, 113, 105, 99, 93, 89, 87, 85, 86, 89, 95, 106, 123, 105, 99, 96, 96, 98, 101, 106, 112, 119, 128, 137, 147, 157, 168, 180, 193, 182, 171, 161, 151, 141, 133, 125, 118, 113, 108, 106, 106, 108, 115, 116, 114, 115, 118, 123, 129, 137, 145, 154, 164, 174, 184, 195, 206, 216, 226, 216, 205, 195, 185, 175, 165, 156, 147, 139, 133, 127, 123, 121, 124, 127, 129, 134, 141, 148, 156, 165, 174, 184, 194, 204, 214, 224, 233, 242, 253, 246, 238, 229, 221, 211, 202, 192, 182, 173, 164, 155, 147, 140, 133, 134, 142, 151, 160, 169, 179, 188, 198, 207, 216, 225, 233, 241, 247, 253, 255, 251, 247, 241, 234, 227, 219, 210, 201, 192, 182, 173, 163, 153, 142, 134, 151, 163, 174, 184, 194, 203, 212, 220, 227, 233, 239, 243, 247, 249, 242, 242, 241, 238, 235, 230, 225, 218, 211, 203, 194, 184, 173, 161, 146, 155, 170, 182, 192, 201, 208, 215, 221, 226, 229, 231, 232, 232, 231, 228, 215, 219, 221, 223, 223, 221, 219, 215, 210, 204, 197, 188, 177, 164, 144, 154, 170, 182, 191, 198, 204, 208, 211, 212, 213, 212, 209, 205, 200, 194 }; const uint8_t coordsY[NUM_PIXELS] { 6, 14, 22, 31, 41, 50, 60, 70, 80, 89, 98, 106, 114, 120, 125, 128, 124, 116, 109, 101, 92, 82, 73, 63, 54, 44, 35, 27, 18, 11, 4, 0, 5, 10, 17, 24, 32, 40, 49, 59, 68, 78, 87, 97, 106, 116, 121, 106, 95, 85, 75, 65, 56, 47, 38, 31, 24, 17, 12, 7, 4, 10, 10, 13, 16, 20, 25, 31, 39, 46, 55, 64, 74, 85, 96, 111, 101, 87, 76, 65, 56, 48, 41, 34, 29, 25, 21, 20, 19, 19, 21, 33, 30, 29, 28, 29, 31, 34, 39, 45, 51, 59, 69, 79, 92, 111, 101, 85, 73, 64, 56, 50, 45, 41, 39, 38, 38, 40, 43, 47, 52, 68, 62, 56, 53, 50, 49, 49, 50, 53, 57, 63, 70, 80, 94, 119, 106, 89, 78, 70, 65, 61, 59, 59, 60, 62, 66, 71, 77, 84, 92, 119, 109, 100, 92, 85, 80, 75, 72, 70, 70, 71, 74, 79, 87, 99, 114, 97, 88, 83, 81, 80, 81, 84, 88, 94, 100, 108, 116, 126, 136, 163, 152, 142, 132, 123, 114, 107, 101, 96, 93, 91, 91, 93, 98, 108, 108, 102, 101, 101, 104, 108, 114, 120, 128, 137, 146, 157, 167, 178, 190, 203, 192, 181, 170, 160, 150, 141, 133, 126, 119, 115, 111, 110, 111, 118, 119, 118, 120, 124, 130, 136, 144, 153, 162, 172, 182, 193, 203, 214, 224, 232, 223, 213, 202, 192, 182, 172, 163, 154, 146, 139, 132, 128, 125, 126, 129, 133, 139, 146, 154, 162, 172, 181, 191, 201, 210, 220, 229, 238, 246, 255, 249, 242, 234, 225, 216, 207, 197, 188, 178, 169, 160, 151, 143, 136, 135, 145, 155, 164, 174, 183, 193, 202, 211, 220, 228, 236, 243, 249, 254, 253, 250, 246, 242, 236, 229, 222, 213, 205, 196, 186, 176, 166, 155, 143, 133, 153, 166, 177, 187, 196, 205, 214, 221, 228, 234, 238, 242, 245, 246, 246, 236, 237, 237, 236, 233, 229, 225, 219, 212, 204, 195, 186, 175, 162, 146, 156, 171, 182, 192, 201, 208, 214, 220, 223, 226, 228, 228, 227, 224, 221, 207, 211, 215, 217, 218, 218, 216, 213, 209, 203, 196, 187, 177, 164, 142, 153, 170, 181, 190, 196, 201, 205, 207, 208, 207, 205, 202, 197, 191, 184, 159, 168, 176, 182, 188, 192, 195, 197, 197, 196, 193, 189, 182, 173, 160, 146, 164, 173, 180, 184, 186, 186, 185, 183, 179, 174, 167, 160, 151, 142, 114, 125, 135, 144, 152, 159, 165, 170, 173, 175, 176, 174, 171, 164, 153, 136, 154, 161, 164, 165, 164, 162, 157, 152, 145, 138, 129, 119, 109, 98, 72, 83, 94, 105, 114, 124, 132, 139, 145, 150, 153, 155, 155, 152, 143, 142, 146, 146, 143, 139, 134, 127, 119, 110, 101, 91, 81, 70, 59, 48, 37, 48, 58, 69, 79, 89, 99, 108, 116, 123, 129, 134, 137, 138, 134, 132, 130, 126, 121, 114, 106, 98, 88, 79, 69, 59, 48, 38, 29, 19 }; const uint8_t angles[NUM_PIXELS] { 205, 208, 211, 215, 218, 221, 225, 228, 231, 235, 238, 242, 245, 248, 252, 255, 246, 243, 239, 236, 233, 229, 226, 223, 219, 216, 213, 209, 206, 203, 199, 190, 194, 197, 200, 204, 207, 211, 214, 217, 221, 224, 227, 231, 234, 237, 232, 229, 225, 222, 219, 215, 212, 208, 205, 202, 198, 195, 192, 188, 185, 176, 180, 183, 186, 190, 193, 196, 200, 203, 206, 210, 213, 216, 220, 223, 214, 211, 208, 204, 201, 198, 194, 191, 188, 184, 181, 177, 174, 171, 167, 162, 165, 169, 172, 175, 179, 182, 185, 189, 192, 196, 199, 202, 206, 209, 200, 197, 193, 190, 187, 183, 180, 177, 173, 170, 167, 163, 160, 157, 153, 148, 151, 154, 158, 161, 165, 168, 171, 175, 178, 181, 185, 188, 191, 195, 186, 183, 179, 176, 173, 169, 166, 162, 159, 156, 152, 149, 146, 142, 139, 130, 133, 137, 140, 144, 147, 150, 154, 157, 160, 164, 167, 170, 174, 177, 172, 168, 165, 162, 158, 155, 152, 148, 145, 141, 138, 135, 131, 128, 125, 116, 119, 123, 126, 129, 133, 136, 139, 143, 146, 149, 153, 156, 160, 163, 154, 151, 147, 144, 141, 137, 134, 131, 127, 124, 121, 117, 114, 110, 107, 102, 105, 108, 112, 115, 118, 122, 125, 129, 132, 135, 139, 142, 145, 149, 140, 137, 133, 130, 126, 123, 120, 116, 113, 110, 106, 103, 100, 96, 93, 87, 91, 94, 98, 101, 104, 108, 111, 114, 118, 121, 124, 128, 131, 134, 126, 122, 119, 116, 112, 109, 106, 102, 99, 95, 92, 89, 85, 82, 79, 70, 73, 77, 80, 83, 87, 90, 93, 97, 100, 103, 107, 110, 114, 117, 111, 108, 105, 101, 98, 95, 91, 88, 85, 81, 78, 74, 71, 68, 64, 56, 59, 62, 66, 69, 72, 76, 79, 82, 86, 89, 93, 96, 99, 103, 97, 94, 90, 87, 84, 80, 77, 74, 70, 67, 64, 60, 57, 54, 50, 47, 41, 45, 48, 51, 55, 58, 62, 65, 68, 72, 75, 78, 82, 85, 88, 80, 76, 73, 70, 66, 63, 59, 56, 53, 49, 46, 43, 39, 36, 33, 27, 31, 34, 37, 41, 44, 47, 51, 54, 57, 61, 64, 67, 71, 74, 65, 62, 59, 55, 52, 49, 45, 42, 39, 35, 32, 28, 25, 22, 18, 10, 13, 16, 20, 23, 26, 30, 33, 36, 40, 43, 47, 50, 53, 57, 51, 48, 44, 41, 38, 34, 31, 28, 24, 21, 18, 14, 11, 8, 4, 251, 254, 2, 5, 9, 12, 16, 19, 22, 26, 29, 32, 36, 39, 42, 37, 34, 30, 27, 24, 20, 17, 13, 10, 7, 3, 0, 252, 249, 245, 236, 240, 243, 247, 250, 253, 1, 5, 8, 11, 15, 18, 21, 25, 28, 19, 16, 13, 9, 6, 3, 255, 251, 248, 244, 241, 238, 234, 231, 228, 222, 226, 229, 232, 236, 239, 242, 246, 249, 252, 0, 4, 7, 11, 14, 5, 2, 254, 250, 247, 244, 240, 237, 234, 230, 227, 223, 220, 217, 213 }; - // 512 pixels, but some calculations require range 0..255. - // Therefore, define new array with each element == `physicalToFibonacci[i] / 2` - const uint8_t radii[NUM_PIXELS] { 255, 238, 221, 204, 187, 170, 153, 136, 119, 102, 85, 68, 51, 34, 17, 0, 6, 23, 40, 57, 74, 91, 108, 125, 142, 159, 176, 193, 210, 227, 244, 251, 234, 217, 200, 183, 166, 149, 132, 115, 98, 81, 64, 47, 30, 13, 2, 19, 36, 53, 70, 87, 104, 121, 138, 155, 172, 189, 206, 223, 240, 247, 230, 213, 196, 179, 162, 145, 128, 111, 94, 77, 60, 43, 26, 9, 15, 32, 49, 66, 83, 100, 117, 134, 151, 168, 185, 202, 219, 236, 253, 243, 226, 209, 192, 175, 158, 141, 124, 107, 90, 73, 56, 39, 22, 5, 11, 28, 45, 62, 79, 96, 113, 130, 147, 164, 181, 198, 215, 232, 249, 239, 222, 205, 188, 171, 154, 137, 120, 103, 86, 69, 52, 35, 18, 1, 7, 24, 41, 58, 75, 92, 109, 126, 143, 160, 177, 194, 211, 228, 245, 252, 235, 218, 201, 184, 167, 150, 133, 116, 99, 82, 65, 48, 31, 14, 3, 20, 37, 54, 71, 88, 105, 122, 139, 156, 173, 190, 207, 224, 241, 248, 231, 214, 197, 180, 163, 146, 129, 112, 95, 78, 61, 44, 27, 10, 16, 33, 50, 67, 84, 101, 118, 135, 152, 169, 186, 203, 220, 237, 254, 244, 227, 210, 193, 176, 159, 142, 125, 108, 91, 74, 57, 40, 23, 6, 12, 29, 46, 63, 80, 97, 114, 131, 148, 165, 182, 199, 216, 233, 250, 240, 223, 206, 189, 172, 155, 138, 121, 104, 87, 70, 53, 36, 19, 2, 8, 25, 42, 59, 76, 93, 110, 127, 144, 161, 178, 195, 212, 229, 246, 253, 236, 219, 202, 185, 168, 151, 134, 117, 100, 83, 66, 49, 32, 15, 4, 21, 38, 55, 72, 89, 106, 123, 140, 157, 174, 191, 208, 225, 242, 249, 232, 215, 198, 181, 164, 147, 130, 113, 96, 79, 62, 45, 28, 11, 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255, 245, 228, 211, 194, 177, 160, 143, 126, 109, 92, 75, 58, 41, 24, 7, 13, 30, 47, 64, 81, 98, 115, 132, 149, 166, 183, 200, 217, 234, 251, 241, 224, 207, 190, 173, 156, 139, 122, 105, 88, 71, 54, 37, 20, 3, 9, 26, 43, 60, 77, 94, 111, 128, 145, 162, 179, 196, 213, 230, 247, 254, 237, 220, 203, 186, 169, 152, 135, 118, 101, 84, 67, 50, 33, 16, 5, 22, 39, 56, 73, 90, 107, 124, 141, 158, 175, 192, 209, 226, 243, 250, 233, 216, 199, 182, 165, 148, 131, 114, 97, 80, 63, 46, 29, 12, 1, 18, 35, 52, 69, 86, 103, 120, 137, 154, 171, 188, 205, 222, 239, 246, 229, 212, 195, 178, 161, 144, 127, 110, 93, 76, 59, 42, 25, 8, 14, 31, 48, 65, 82, 99, 116, 133, 150, 167, 184, 201, 218, 235, 252, 242, 225, 208, 191, 174, 157, 140, 123, 106, 89, 72, 55, 38, 21, 4, 10, 27, 44, 61, 78, 95, 112, 129, 146, 163, 180, 197, 214, 231, 248 }; #elif defined(PRODUCT_FIBONACCI256) - const uint16_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 39, 52, 65, 78, 91, 104, 117, 130, 143, 156, 169, 182, 195, 208, 221, 234, 247, 252, 239, 226, 213, 200, 187, 174, 161, 148, 135, 122, 109, 96, 83, 70, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 75, 88, 101, 114, 127, 140, 153, 166, 179, 192, 205, 218, 231, 244, 249, 236, 223, 210, 197, 184, 171, 158, 145, 132, 119, 106, 93, 80, 67, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189, 202, 215, 228, 241, 254, 246, 233, 220, 207, 194, 181, 168, 155, 142, 129, 116, 103, 90, 77, 64, 51, 38, 25, 12, 4, 17, 30, 43, 56, 69, 82, 95, 108, 121, 134, 147, 160, 173, 186, 199, 212, 225, 238, 251, 243, 230, 217, 204, 191, 178, 165, 152, 139, 126, 113, 100, 87, 74, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 66, 79, 92, 105, 118, 131, 144, 157, 170, 183, 196, 209, 222, 235, 248, 253, 240, 227, 214, 201, 188, 175, 162, 149, 136, 123, 110, 97, 84, 71, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 76, 89, 102, 115, 128, 141, 154, 167, 180, 193, 206, 219, 232, 245, 250, 237, 224, 211, 198, 185, 172, 159, 146, 133, 120, 107, 94, 81, 68, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60, 73, 86, 99, 112, 125, 138, 151, 164, 177, 190, 203, 216, 229, 242, 255 }; - const uint16_t fibonacciToPhysical[NUM_PIXELS] { 0, 157, 78, 235, 118, 39, 196, 79, 236, 156, 40, 197, 117, 1, 158, 77, 234, 119, 38, 195, 80, 237, 155, 41, 198, 116, 2, 159, 76, 233, 120, 37, 194, 81, 238, 154, 42, 199, 115, 3, 160, 75, 232, 121, 36, 193, 82, 239, 153, 43, 200, 114, 4, 161, 74, 231, 122, 35, 192, 83, 240, 152, 44, 201, 113, 5, 162, 73, 230, 123, 34, 191, 84, 241, 151, 45, 202, 112, 6, 163, 72, 229, 124, 33, 190, 85, 242, 150, 46, 203, 111, 7, 164, 71, 228, 125, 32, 189, 86, 243, 149, 47, 204, 110, 8, 165, 70, 227, 126, 31, 188, 87, 244, 148, 48, 205, 109, 9, 166, 69, 226, 127, 30, 187, 88, 245, 147, 49, 206, 108, 10, 167, 68, 225, 128, 29, 186, 89, 246, 146, 50, 207, 107, 11, 168, 67, 224, 129, 28, 185, 90, 247, 145, 51, 208, 106, 12, 169, 66, 223, 130, 27, 184, 91, 248, 144, 52, 209, 105, 13, 170, 65, 222, 131, 26, 183, 92, 249, 143, 53, 210, 104, 14, 171, 64, 221, 132, 25, 182, 93, 250, 142, 54, 211, 103, 15, 172, 63, 220, 133, 24, 181, 94, 251, 141, 55, 212, 102, 16, 173, 62, 219, 134, 23, 180, 95, 252, 140, 56, 213, 101, 17, 174, 61, 218, 135, 22, 179, 96, 253, 139, 57, 214, 100, 18, 175, 60, 217, 136, 21, 178, 97, 254, 138, 58, 215, 99, 19, 176, 59, 216, 137, 20, 177, 98, 255 }; + const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 39, 52, 65, 78, 91, 104, 117, 130, 143, 156, 169, 182, 195, 208, 221, 234, 247, 252, 239, 226, 213, 200, 187, 174, 161, 148, 135, 122, 109, 96, 83, 70, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 75, 88, 101, 114, 127, 140, 153, 166, 179, 192, 205, 218, 231, 244, 249, 236, 223, 210, 197, 184, 171, 158, 145, 132, 119, 106, 93, 80, 67, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189, 202, 215, 228, 241, 254, 246, 233, 220, 207, 194, 181, 168, 155, 142, 129, 116, 103, 90, 77, 64, 51, 38, 25, 12, 4, 17, 30, 43, 56, 69, 82, 95, 108, 121, 134, 147, 160, 173, 186, 199, 212, 225, 238, 251, 243, 230, 217, 204, 191, 178, 165, 152, 139, 126, 113, 100, 87, 74, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 66, 79, 92, 105, 118, 131, 144, 157, 170, 183, 196, 209, 222, 235, 248, 253, 240, 227, 214, 201, 188, 175, 162, 149, 136, 123, 110, 97, 84, 71, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 76, 89, 102, 115, 128, 141, 154, 167, 180, 193, 206, 219, 232, 245, 250, 237, 224, 211, 198, 185, 172, 159, 146, 133, 120, 107, 94, 81, 68, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60, 73, 86, 99, 112, 125, 138, 151, 164, 177, 190, 203, 216, 229, 242, 255 }; + const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 157, 78, 235, 118, 39, 196, 79, 236, 156, 40, 197, 117, 1, 158, 77, 234, 119, 38, 195, 80, 237, 155, 41, 198, 116, 2, 159, 76, 233, 120, 37, 194, 81, 238, 154, 42, 199, 115, 3, 160, 75, 232, 121, 36, 193, 82, 239, 153, 43, 200, 114, 4, 161, 74, 231, 122, 35, 192, 83, 240, 152, 44, 201, 113, 5, 162, 73, 230, 123, 34, 191, 84, 241, 151, 45, 202, 112, 6, 163, 72, 229, 124, 33, 190, 85, 242, 150, 46, 203, 111, 7, 164, 71, 228, 125, 32, 189, 86, 243, 149, 47, 204, 110, 8, 165, 70, 227, 126, 31, 188, 87, 244, 148, 48, 205, 109, 9, 166, 69, 226, 127, 30, 187, 88, 245, 147, 49, 206, 108, 10, 167, 68, 225, 128, 29, 186, 89, 246, 146, 50, 207, 107, 11, 168, 67, 224, 129, 28, 185, 90, 247, 145, 51, 208, 106, 12, 169, 66, 223, 130, 27, 184, 91, 248, 144, 52, 209, 105, 13, 170, 65, 222, 131, 26, 183, 92, 249, 143, 53, 210, 104, 14, 171, 64, 221, 132, 25, 182, 93, 250, 142, 54, 211, 103, 15, 172, 63, 220, 133, 24, 181, 94, 251, 141, 55, 212, 102, 16, 173, 62, 219, 134, 23, 180, 95, 252, 140, 56, 213, 101, 17, 174, 61, 218, 135, 22, 179, 96, 253, 139, 57, 214, 100, 18, 175, 60, 217, 136, 21, 178, 97, 254, 138, 58, 215, 99, 19, 176, 59, 216, 137, 20, 177, 98, 255 }; const uint8_t coordsX[NUM_PIXELS] { 133, 156, 165, 168, 165, 158, 147, 132, 114, 95, 76, 57, 41, 28, 19, 15, 17, 24, 37, 56, 123, 96, 73, 53, 38, 28, 24, 25, 31, 41, 55, 71, 89, 106, 122, 136, 146, 152, 152, 143, 138, 136, 128, 115, 101, 85, 70, 56, 44, 37, 33, 34, 41, 53, 69, 90, 114, 140, 167, 226, 204, 180, 154, 129, 106, 85, 67, 54, 46, 43, 44, 50, 60, 72, 86, 100, 113, 123, 128, 117, 104, 90, 78, 67, 59, 54, 54, 59, 68, 82, 100, 121, 143, 167, 191, 212, 231, 246, 255, 251, 251, 245, 233, 218, 199, 178, 156, 134, 114, 96, 82, 73, 67, 66, 70, 78, 89, 103, 111, 94, 84, 80, 81, 86, 96, 109, 126, 145, 165, 185, 204, 220, 233, 241, 244, 241, 232, 217, 179, 201, 217, 229, 235, 235, 230, 220, 207, 190, 172, 154, 136, 121, 108, 99, 95, 96, 104, 120, 110, 111, 118, 130, 144, 160, 176, 192, 206, 217, 224, 227, 224, 216, 202, 184, 162, 137, 110, 44, 68, 94, 120, 145, 168, 187, 202, 212, 216, 216, 212, 203, 191, 177, 162, 148, 135, 126, 122, 136, 147, 161, 174, 186, 197, 204, 206, 205, 198, 187, 172, 152, 130, 106, 81, 58, 36, 17, 0, 5, 15, 30, 49, 71, 93, 116, 138, 157, 173, 185, 192, 195, 193, 187, 178, 166, 152, 137, 149, 164, 175, 180, 182, 179, 171, 159, 143, 125, 105, 83, 63, 44, 28, 16, 9, 7, 12, 23 }; const uint8_t coordsY[NUM_PIXELS] { 126, 120, 109, 96, 82, 69, 57, 49, 45, 45, 50, 59, 74, 92, 114, 138, 163, 188, 211, 231, 255, 248, 235, 218, 198, 175, 152, 129, 107, 89, 74, 63, 57, 56, 59, 66, 76, 88, 102, 116, 103, 88, 77, 71, 68, 70, 77, 88, 103, 121, 141, 163, 184, 205, 222, 236, 245, 249, 247, 208, 224, 235, 241, 240, 234, 223, 209, 191, 172, 152, 132, 115, 101, 90, 84, 82, 86, 95, 114, 107, 98, 98, 103, 112, 126, 142, 159, 177, 195, 210, 222, 230, 233, 230, 223, 209, 191, 168, 142, 98, 125, 151, 174, 194, 209, 219, 223, 223, 218, 208, 195, 180, 164, 148, 134, 122, 114, 112, 123, 128, 138, 151, 165, 180, 193, 203, 211, 214, 212, 206, 194, 178, 158, 134, 109, 83, 58, 35, 11, 28, 48, 71, 95, 120, 142, 163, 179, 192, 200, 203, 202, 196, 187, 175, 162, 148, 136, 133, 152, 166, 177, 186, 190, 191, 187, 178, 165, 148, 128, 107, 84, 62, 41, 24, 11, 2, 0, 28, 16, 9, 8, 13, 23, 37, 55, 75, 96, 116, 135, 151, 164, 173, 177, 177, 172, 162, 146, 153, 161, 163, 160, 152, 139, 124, 106, 87, 69, 51, 36, 25, 18, 16, 20, 29, 44, 64, 133, 106, 81, 60, 44, 32, 26, 25, 29, 38, 50, 65, 82, 99, 115, 129, 140, 147, 148, 138, 134, 131, 122, 110, 95, 80, 65, 52, 42, 36, 34, 37, 45, 59, 77, 98, 123, 149, 176, 202 }; const uint8_t angles[NUM_PIXELS] { 0, 247, 238, 229, 220, 211, 203, 194, 185, 176, 167, 159, 150, 141, 132, 123, 115, 106, 97, 88, 65, 74, 83, 92, 100, 109, 118, 127, 136, 144, 153, 162, 171, 180, 188, 197, 206, 215, 224, 232, 209, 201, 192, 183, 174, 165, 157, 148, 139, 130, 121, 113, 104, 95, 86, 77, 69, 60, 51, 28, 37, 46, 54, 63, 72, 81, 90, 98, 107, 116, 125, 134, 142, 151, 160, 169, 178, 186, 195, 172, 163, 155, 146, 137, 128, 119, 111, 102, 93, 84, 75, 67, 58, 49, 40, 31, 23, 14, 5, 246, 255, 8, 17, 26, 35, 44, 52, 61, 70, 79, 88, 96, 105, 114, 123, 132, 140, 149, 135, 126, 117, 108, 100, 91, 82, 73, 64, 56, 47, 38, 29, 20, 12, 3, 250, 241, 232, 223, 209, 218, 227, 235, 244, 253, 6, 15, 24, 33, 41, 50, 59, 68, 77, 85, 94, 103, 112, 98, 89, 80, 71, 62, 54, 45, 36, 27, 18, 10, 1, 247, 239, 230, 221, 212, 203, 195, 186, 163, 172, 180, 189, 198, 207, 216, 224, 233, 242, 251, 4, 13, 22, 31, 39, 48, 57, 66, 75, 52, 43, 34, 25, 16, 8, 254, 245, 237, 228, 219, 210, 201, 193, 184, 175, 166, 157, 149, 126, 134, 143, 152, 161, 170, 178, 187, 196, 205, 214, 222, 231, 240, 249, 2, 11, 20, 28, 37, 14, 5, 252, 243, 235, 226, 217, 208, 199, 191, 182, 173, 164, 155, 147, 138, 129, 120, 111, 103 }; - // with <= 256 pixels, can create an array reference variable (zero flash/ram cost) - const uint8_t (&radii)[NUM_PIXELS] = physicalToFibonacci; #elif defined(PRODUCT_FIBONACCI128) - const uint16_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 39, 52, 65, 78, 91, 104, 117, 122, 109, 96, 83, 70, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 75, 88, 101, 114, 127, 119, 106, 93, 80, 67, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 116, 103, 90, 77, 64, 51, 38, 25, 12, 4, 17, 30, 43, 56, 69, 82, 95, 108, 121, 126, 113, 100, 87, 74, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 66, 79, 92, 105, 118, 123, 110, 97, 84, 71, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 76, 89, 102, 115, 120, 107, 94, 81, 68, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60, 73, 86, 99, 112, 125 }; - const uint16_t fibonacciToPhysical[NUM_PIXELS] { 0, 79, 39, 117, 59, 19, 98, 40, 118, 78, 20, 99, 58, 1, 80, 38, 116, 60, 18, 97, 41, 119, 77, 21, 100, 57, 2, 81, 37, 115, 61, 17, 96, 42, 120, 76, 22, 101, 56, 3, 82, 36, 114, 62, 16, 95, 43, 121, 75, 23, 102, 55, 4, 83, 35, 113, 63, 15, 94, 44, 122, 74, 24, 103, 54, 5, 84, 34, 112, 64, 14, 93, 45, 123, 73, 25, 104, 53, 6, 85, 33, 111, 65, 13, 92, 46, 124, 72, 26, 105, 52, 7, 86, 32, 110, 66, 12, 91, 47, 125, 71, 27, 106, 51, 8, 87, 31, 109, 67, 11, 90, 48, 126, 70, 28, 107, 50, 9, 88, 30, 108, 68, 10, 89, 49, 127, 69, 29 }; + const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 39, 52, 65, 78, 91, 104, 117, 122, 109, 96, 83, 70, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 75, 88, 101, 114, 127, 119, 106, 93, 80, 67, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 116, 103, 90, 77, 64, 51, 38, 25, 12, 4, 17, 30, 43, 56, 69, 82, 95, 108, 121, 126, 113, 100, 87, 74, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 66, 79, 92, 105, 118, 123, 110, 97, 84, 71, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 76, 89, 102, 115, 120, 107, 94, 81, 68, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60, 73, 86, 99, 112, 125 }; + const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 79, 39, 117, 59, 19, 98, 40, 118, 78, 20, 99, 58, 1, 80, 38, 116, 60, 18, 97, 41, 119, 77, 21, 100, 57, 2, 81, 37, 115, 61, 17, 96, 42, 120, 76, 22, 101, 56, 3, 82, 36, 114, 62, 16, 95, 43, 121, 75, 23, 102, 55, 4, 83, 35, 113, 63, 15, 94, 44, 122, 74, 24, 103, 54, 5, 84, 34, 112, 64, 14, 93, 45, 123, 73, 25, 104, 53, 6, 85, 33, 111, 65, 13, 92, 46, 124, 72, 26, 105, 52, 7, 86, 32, 110, 66, 12, 91, 47, 125, 71, 27, 106, 51, 8, 87, 31, 109, 67, 11, 90, 48, 126, 70, 28, 107, 50, 9, 88, 30, 108, 68, 10, 89, 49, 127, 69, 29 }; const uint8_t coordsX[NUM_PIXELS] { 137, 170, 182, 186, 182, 172, 156, 135, 110, 83, 26, 49, 74, 99, 121, 141, 155, 164, 164, 151, 145, 141, 129, 112, 91, 69, 47, 27, 11, 0, 9, 11, 19, 33, 50, 70, 90, 108, 123, 130, 114, 96, 77, 58, 43, 32, 25, 25, 32, 45, 85, 65, 51, 43, 42, 47, 58, 74, 94, 105, 81, 68, 62, 63, 70, 84, 103, 127, 154, 218, 193, 167, 142, 119, 101, 89, 83, 84, 96, 118, 104, 106, 116, 132, 152, 175, 198, 221, 241, 255, 248, 236, 219, 199, 178, 158, 140, 126, 121, 140, 157, 176, 195, 213, 227, 237, 241, 239, 193, 210, 221, 225, 222, 214, 201, 184, 164, 142, 160, 181, 196, 204, 206, 202, 191, 174, 152, 125 }; const uint8_t coordsY[NUM_PIXELS] { 130, 121, 105, 86, 66, 47, 31, 19, 13, 13, 55, 39, 30, 28, 33, 43, 57, 75, 95, 115, 96, 75, 60, 50, 46, 49, 59, 74, 96, 122, 166, 139, 114, 93, 78, 69, 67, 72, 85, 112, 102, 90, 89, 96, 110, 129, 152, 177, 203, 227, 247, 228, 207, 184, 161, 140, 123, 112, 109, 126, 132, 146, 165, 185, 206, 225, 240, 251, 255, 224, 235, 240, 237, 229, 216, 199, 181, 161, 143, 139, 166, 186, 202, 215, 221, 222, 216, 204, 185, 115, 142, 166, 184, 197, 203, 202, 195, 181, 158, 167, 180, 182, 178, 166, 148, 126, 101, 74, 21, 42, 66, 91, 114, 134, 150, 159, 160, 147, 141, 137, 124, 106, 85, 63, 42, 24, 9, 0 }; const uint8_t angles[NUM_PIXELS] { 0, 247, 239, 230, 221, 212, 203, 194, 186, 177, 154, 163, 171, 180, 189, 198, 207, 216, 224, 233, 210, 201, 192, 184, 175, 166, 157, 148, 139, 131, 116, 125, 134, 143, 152, 160, 169, 178, 187, 196, 173, 164, 155, 146, 137, 129, 120, 111, 102, 93, 79, 88, 97, 105, 114, 123, 132, 141, 150, 135, 126, 118, 109, 100, 91, 82, 73, 65, 56, 33, 42, 50, 59, 68, 77, 86, 95, 103, 112, 98, 89, 80, 71, 63, 54, 45, 36, 27, 18, 252, 4, 13, 22, 31, 39, 48, 57, 66, 75, 52, 43, 34, 25, 16, 8, 255, 246, 237, 214, 223, 232, 241, 250, 2, 11, 20, 29, 37, 14, 5, 253, 244, 235, 226, 218, 209, 200, 191 }; - // with <= 256 pixels, can create an array reference variable (zero flash/ram cost) - const uint8_t (&radii)[NUM_PIXELS] = physicalToFibonacci; +#elif defined(PRODUCT_FIBONACCI64_FULL) || defined(PRODUCT_FIBONACCI64_MINI) + const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 39, 52, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 51, 38, 25, 12, 4, 17, 30, 43, 56, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60 }; + const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 39, 19, 58, 29, 9, 48, 20, 59, 38, 10, 49, 28, 1, 40, 18, 57, 30, 8, 47, 21, 60, 37, 11, 50, 27, 2, 41, 17, 56, 31, 7, 46, 22, 61, 36, 12, 51, 26, 3, 42, 16, 55, 32, 6, 45, 23, 62, 35, 13, 52, 25, 4, 43, 15, 54, 33, 5, 44, 24, 63, 34, 14, 53 }; + const uint8_t coordsX[NUM_PIXELS] { 140, 189, 208, 214, 208, 146, 168, 180, 180, 162, 152, 146, 129, 103, 72, 40, 70, 97, 120, 131, 107, 79, 50, 23, 0, 7, 23, 46, 76, 93, 57, 37, 28, 29, 87, 68, 59, 62, 80, 113, 91, 94, 109, 133, 202, 172, 145, 125, 117, 145, 170, 198, 227, 253, 255, 235, 210, 181, 148, 175, 207, 228, 240, 244 }; + const uint8_t coordsY[NUM_PIXELS] { 128, 114, 91, 63, 34, 0, 21, 48, 76, 106, 78, 47, 25, 11, 5, 38, 35, 42, 61, 101, 87, 69, 68, 78, 98, 143, 118, 102, 98, 122, 131, 152, 179, 209, 255, 230, 202, 174, 148, 142, 181, 210, 235, 252, 235, 234, 224, 203, 170, 183, 201, 205, 198, 181, 134, 157, 171, 173, 153, 145, 138, 120, 93, 63 }; + const uint8_t angles[NUM_PIXELS] { 0, 249, 241, 232, 223, 200, 208, 217, 226, 235, 212, 203, 194, 185, 176, 162, 171, 180, 188, 197, 174, 165, 156, 147, 139, 124, 133, 142, 151, 136, 128, 119, 110, 101, 78, 86, 95, 104, 113, 99, 90, 81, 72, 63, 40, 49, 58, 67, 75, 52, 43, 34, 25, 17, 2, 11, 20, 29, 38, 14, 6, 255, 246, 237 }; +#elif defined(PRODUCT_FIBONACCI32) + const uint8_t physicalToFibonacci[NUM_PIXELS] = { 0, 13, 26, 31, 18, 5, 10, 23, 28, 15, 2, 7, 20, 33, 25, 12, 4, 17, 30, 22, 9, 1, 14, 27, 32, 19, 6, 11, 24, 29, 16, 3, 8, 21 }; + const uint8_t fibonacciToPhysical[NUM_PIXELS] = { 0, 21, 10, 31, 16, 5, 26, 11, 32, 20, 6, 27, 15, 1, 22, 9, 30, 17, 4, 25, 12, 33, 19, 7, 28, 14, 2, 23, 8, 29, 18, 3, 24, 13 }; + const uint8_t coordsX[NUM_PIXELS] = { 152, 224, 252, 210, 211, 184, 169, 161, 89, 121, 138, 102, 61, 19, 13, 57, 82, 29, 0, 36, 63, 111, 79, 83, 158, 129, 118, 160, 196, 255, 212, 163, 203, 250 }; + const uint8_t coordsY[NUM_PIXELS] = { 120, 101, 69, 7, 48, 90, 50, 7, 0, 27, 83, 62, 37, 35, 84, 78, 112, 125, 154, 185, 149, 140, 195, 236, 255, 226, 179, 198, 223, 181, 183, 156, 144, 135 }; + const uint8_t angles[NUM_PIXELS] = { 255, 246, 237, 214, 223, 232, 208, 199, 176, 185, 193, 170, 161, 152, 138, 147, 132, 123, 114, 100, 108, 94, 85, 76, 53, 62, 70, 47, 38, 15, 23, 32, 9, 0 }; #else #error "Unknown / Unsupported fibonacci product ... no mappings defined" #endif @@ -62,7 +89,9 @@ static_assert(NUM_PIXELS == ARRAY_SIZE2(fibonacciToPhysical), ""); static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsX), ""); static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsY), ""); static_assert(NUM_PIXELS == ARRAY_SIZE2(angles), ""); -static_assert(NUM_PIXELS == ARRAY_SIZE2(radii), ""); + +static const uint8_t RADII_SCALE_FACTOR { static_eval::value }; + void drawSpiralLine(uint8_t angle, int step, CRGB color) { @@ -158,6 +187,10 @@ void antialiasPixelAR(uint8_t angle, uint8_t dAngle, uint8_t startRadius, uint8_ } } +// TODO - anglePalette() from Fib32 sets `hues = 256 / NUM_PIXELS' ... which is ZERO(!) +// The other similar functions are hard-coded to `hues = 1` even on Fib32. +// Likely a bug in Fib32 branch for this one function? +// Check if other branches did similar, or set to hard-coded value of 1? void anglePalette() { uint16_t hues = 1; @@ -172,8 +205,7 @@ void radiusPalette() { uint16_t hues = 1; for (uint16_t i = 0; i < NUM_PIXELS; i++) { - uint16_t r = radii[i]; - + uint8_t r = physicalToFibonacci[i] / RADII_SCALE_FACTOR; leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - (r * hues)); } } @@ -223,7 +255,7 @@ void radiusGradientPalette() { uint16_t hues = 1; for (uint16_t i = 0; i < NUM_PIXELS; i++) { - uint16_t r = radii[i]; + uint8_t r = physicalToFibonacci[i] / RADII_SCALE_FACTOR; leds[i] = ColorFromPalette(gCurrentPalette, beat8(speed) - (r * hues)); } @@ -263,6 +295,11 @@ void xyGradientPalette() { // TODO: Fib512 calculates the angles replacing `64` in EVERY_N_MILLIS() with `255`. // Is this a bug in Fib512, or a bug in Fib256 and Fib128? +// TODO: Fib64 has different hard-coded numbers within `drawAnalogClock()` also. +// It appears these *might* correspond to maximum radius to draw the corresponding +// hand for? If correct, the definition those magic numbers would need to be added +// to the product configuration section. + // calls antialiasPixelAR, which requires physicalToFibonacci array) void drawAnalogClock() { float second = timeClient.getSeconds(); @@ -299,8 +336,14 @@ void drawAnalogClock() { leds[0] = CRGB::Red; } -// TODO: Optimize this so more calculations are within EVERY_N_MILLIS(100) -// TODO: Allow configuration to disable the seconds hand +// TODO: `drawSpiralAnalogClock()` -- review differences between the Fibonacci boards (e.g., hard-coded radii) + +// TODO: `drawSpiralAnalogClock()` -- Optimize more calculations within EVERY_N_MILLIS(100) + +// TODO: `drawSpiralAnalogClock()` -- config to disable the seconds hand? + +// TODO: `drawSpiralAnalogClock***()` -- disable all the below on boards with less than 128 pixels? + void drawSpiralAnalogClock(uint8_t step) { float second = timeClient.getSeconds(); float minute = timeClient.getMinutes() + (second / 60.0); @@ -357,8 +400,12 @@ void drawSpiralAnalogClock21and34() { drawSpiralAnalogClock(34); } -// TODO: Optimize this so more calculations are within EVERY_N_MILLIS(100) -// TODO: Allow configuration to disable the seconds hand +// TODO: `drawSpiralAnalogClock13_21_and_34()` -- Optimize more calculations within EVERY_N_MILLIS(100) + +// TODO: `drawSpiralAnalogClock13_21_and_34()` -- config to disable the seconds hand? + +// TODO: `drawSpiralAnalogClock()` -- review differences between the Fibonacci boards (e.g., hard-coded radii) + void drawSpiralAnalogClock13_21_and_34() { float second = timeClient.getSeconds(); float minute = timeClient.getMinutes() + (second / 60.0); @@ -390,18 +437,18 @@ void drawSpiralAnalogClock13_21_and_34() { void drawSpiralAnalogClock34_21_and_13() { float second = timeClient.getSeconds(); float minute = timeClient.getMinutes() + (second / 60.0); - float hour = timeClient.getHours() + (minute / 60.0); + float hour = timeClient.getHours() + (minute / 60.0); - static uint8_t hourAngle = 0; + static uint8_t hourAngle = 0; static uint8_t minuteAngle = 0; static uint8_t secondAngle = 0; const float degreesPerSecond = 255.0 / 60.0; const float degreesPerMinute = 255.0 / 60.0; - const float degreesPerHour = 255.0 / 12.0; + const float degreesPerHour = 255.0 / 12.0; EVERY_N_MILLIS(100) { - hourAngle = 255 - hour * degreesPerHour; + hourAngle = 255 - hour * degreesPerHour; minuteAngle = 255 - minute * degreesPerMinute; secondAngle = 255 - second * degreesPerSecond; } @@ -410,7 +457,7 @@ void drawSpiralAnalogClock34_21_and_13() { drawSpiralLine(secondAngle, 34, CRGB(0, 0, 2)); drawSpiralLine(minuteAngle, 21, CRGB(0, 2, 0)); - drawSpiralLine(hourAngle, 13, CRGB(2, 0, 0)); + drawSpiralLine(hourAngle, 13, CRGB(2, 0, 0)); } diff --git a/esp8266-fastled-webserver/common.h b/esp8266-fastled-webserver/common.h index d9abee70..a2b5de7c 100644 --- a/esp8266-fastled-webserver/common.h +++ b/esp8266-fastled-webserver/common.h @@ -22,6 +22,7 @@ #include "./include/simplehacks/static_eval.h" #include "./include/simplehacks/constexpr_strlen.h" #include "./include/simplehacks/array_size2.h" + #include "config.h" // must be included before FastLED.h #define FASTLED_INTERNAL // no other way to suppress build warnings @@ -46,6 +47,16 @@ extern "C" { #include #include // https://github.com/tzapu/WiFiManager/tree/development +#if defined(ESP32) || defined(ESP8266) + // Optional: (LGPL) https://github.com/sinricpro/ESPTrueRandom.git#ed198f459da6d7af65dd13317a4fdc97b23991b4 + // #include "ESPTrueRandom.h" + // Then: + // ESPTrueRandom.useRNG = true; + // int32_t r = ESPTrueRandom.memfill((void*)&r, sizeof(r)); +#else + #error "Currently only ESP32 and ESP8266 are supported" +#endif + #if defined(ENABLE_IR) #include #include "commands.h" @@ -65,9 +76,14 @@ extern ESP8266WebServer webServer; extern String nameString; -#if IS_FIBONACCI - extern const uint16_t physicalToFibonacci [NUM_PIXELS]; - extern const uint16_t fibonacciToPhysical [NUM_PIXELS]; +#if IS_FIBONACCI // actual data in map.h + #if NUM_PIXELS > 256 // when more than 256 pixels, cannot store index in uint8_t.... + extern const uint16_t physicalToFibonacci [NUM_PIXELS]; + extern const uint16_t fibonacciToPhysical [NUM_PIXELS]; + #else + extern const uint8_t physicalToFibonacci [NUM_PIXELS]; + extern const uint8_t fibonacciToPhysical [NUM_PIXELS]; + #endif extern const uint8_t coordsX[NUM_PIXELS]; extern const uint8_t coordsY[NUM_PIXELS]; extern const uint8_t angles[NUM_PIXELS]; @@ -92,6 +108,7 @@ typedef PaletteAndName PaletteAndNameList[]; // Function prototypes + // Local C++ sources that are masquerading as header files #include "GradientPalettes.h" #include "Info.h" diff --git a/esp8266-fastled-webserver/config.h b/esp8266-fastled-webserver/config.h index 903b6fb7..733867d6 100644 --- a/esp8266-fastled-webserver/config.h +++ b/esp8266-fastled-webserver/config.h @@ -24,10 +24,15 @@ // When compiling from Arduino, you can edit this file. // When compiling from PlatformIO, this is a reference for compiler flags. -//#define PRODUCT_DEFAULT -//#define PRODUCT_FIBONACCI256 -//#define PRODUCT_FIBONACCI128 -#define PRODUCT_FIBONACCI512 +#define PRODUCT_DEFAULT +// #define PRODUCT_FIBONACCI512 +// #define PRODUCT_FIBONACCI256 +// #define PRODUCT_FIBONACCI128 +// #define PRODUCT_FIBONACCI64_FULL // 86mm, WS2812B-5050, ~60mA/pixel +// #define PRODUCT_FIBONACCI64_MINI // 64mm, WS2812B-3535, ~60mA/pixel +// #define PRODUCT_FIBONACCI64_MICRO // 40mm, WS2812C-2020, ~5mA/pixel +// #define PRODUCT_FIBONACCI64_NANO // 33mm, SK6805-EC15, ~5mA/pixel +// #define PRODUCT_FIBONACCI32 // //////////////////////////////////////////////////////////////////////////////////////////////////// // Additional configuration options ... defaults shown @@ -44,6 +49,10 @@ // Product-specific configuration #if defined(PRODUCT_DEFAULT) #include "include\configs\product\default.h" + #elif defined(PRODUCT_FIBONACCI32) + #include "include\configs\product\fibonacci32.h" + #elif defined(PRODUCT_FIBONACCI64_FULL) || defined(PRODUCT_FIBONACCI64_MINI) || defined(PRODUCT_FIBONACCI64_MICRO) || defined(PRODUCT_FIBONACCI64_NANO) + #include "include\configs\product\fibonacci64.h" #elif defined(PRODUCT_FIBONACCI128) #include "include\configs\product\fibonacci128.h" #elif defined(PRODUCT_FIBONACCI256) diff --git a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino index 52527e29..bfd5bd81 100644 --- a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino +++ b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino @@ -677,6 +677,8 @@ void broadcastString(String name, String value) // webSocketsServer.broadcastTXT(json); } +// TODO: Add board-specific entropy sources + void loop() { // Add entropy to random number generator; we use a lot of it. random16_add_entropy(random(65535)); @@ -1003,6 +1005,88 @@ void loop() { // TODO: Update magic number from 0x55 to 0xAA (or 0x96 or 0x69) +void readSettingsFib32() +{ + // 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) { + return; + } + + brightness = EEPROM.read(0); + + currentPatternIndex = EEPROM.read(1); + if (currentPatternIndex >= patternCount) { + currentPatternIndex = patternCount - 1; + } + + byte r = EEPROM.read(2); + byte g = EEPROM.read(3); + byte b = EEPROM.read(4); + + if (r == 0 && g == 0 && b == 0) + { + } + else + { + solidColor = CRGB(r, g, b); + } + + power = EEPROM.read(5); + + autoplay = EEPROM.read(6); + autoplayDuration = EEPROM.read(7); + + currentPaletteIndex = EEPROM.read(8); + if (currentPaletteIndex >= paletteCount) { + currentPaletteIndex = paletteCount - 1; + } + + showClock = EEPROM.read(9); + clockBackgroundFade = EEPROM.read(10); +} +void readSettingsFib64() +{ + // 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) { + return; + } + + brightness = EEPROM.read(0); + + currentPatternIndex = EEPROM.read(1); + if (currentPatternIndex >= patternCount) { + currentPatternIndex = patternCount - 1; + } + + byte r = EEPROM.read(2); + byte g = EEPROM.read(3); + byte b = EEPROM.read(4); + + if (r == 0 && g == 0 && b == 0) + { + } + else + { + solidColor = CRGB(r, g, b); + } + + power = EEPROM.read(5); + + autoplay = EEPROM.read(6); + autoplayDuration = EEPROM.read(7); + + currentPaletteIndex = EEPROM.read(8); + if (currentPaletteIndex >= paletteCount) { + currentPaletteIndex = paletteCount - 1; + } + + showClock = EEPROM.read(9); + clockBackgroundFade = EEPROM.read(10); +} void readSettingsFib128() { // check for "magic number" so we know settings have been written to EEPROM @@ -1202,6 +1286,10 @@ void readSettings() { readSettingsFib256(); #elif defined(PRODUCT_FIBONACCI128) readSettingsFib128(); + #elif defined(PRODUCT_FIBONACCI64_FULL) || defined(PRODUCT_FIBONACCI64_MINI) || defined(PRODUCT_FIBONACCI64_MICRO) || defined(PRODUCT_FIBONACCI64_NANO) + readSettingsFib64(); + #elif defined(PRODUCT_FIBONACCI32) + readSettingsFib32(); #elif defined(PRODUCT_DEFAULT) readSettingsDefaultProduct(); #else @@ -1209,6 +1297,43 @@ void readSettings() { #endif } +void writeAndCommitSettingsFib32() +{ + EEPROM.write(0, brightness); + EEPROM.write(1, currentPatternIndex); + EEPROM.write(2, solidColor.r); + EEPROM.write(3, solidColor.g); + EEPROM.write(4, solidColor.b); + EEPROM.write(5, power); + EEPROM.write(6, autoplay); + EEPROM.write(7, autoplayDuration); + EEPROM.write(8, currentPaletteIndex); + EEPROM.write(9, showClock); // Note: not previously written for Fib64 boards + EEPROM.write(10, clockBackgroundFade); // Note: not previously written for Fib64 boards + EEPROM.write(511, 55); + EEPROM.commit(); +} +void writeAndCommitSettingsFib64() +{ + EEPROM.write(0, brightness); + EEPROM.write(1, currentPatternIndex); + EEPROM.write(2, solidColor.r); + EEPROM.write(3, solidColor.g); + EEPROM.write(4, solidColor.b); + EEPROM.write(5, power); + EEPROM.write(6, autoplay); + EEPROM.write(7, autoplayDuration); + EEPROM.write(8, currentPaletteIndex); + EEPROM.write(9, twinkleSpeed); + EEPROM.write(10, twinkleDensity); + EEPROM.write(11, cooling); + EEPROM.write(12, sparking); + EEPROM.write(13, coolLikeIncandescent); // Note: not previously written for Fib64 boards + EEPROM.write(14, showClock); // Note: not previously written for Fib64 boards + EEPROM.write(15, clockBackgroundFade); // Note: not previously written for Fib64 boards + EEPROM.write(511, 55); + EEPROM.commit(); +} void writeAndCommitSettingsFib128() { EEPROM.write(0, brightness); @@ -1296,6 +1421,10 @@ void writeAndCommitSettings() writeAndCommitSettingsFib256(); #elif defined(PRODUCT_FIBONACCI128) writeAndCommitSettingsFib128(); + #elif defined(PRODUCT_FIBONACCI64_FULL) || defined(PRODUCT_FIBONACCI64_MINI) || defined(PRODUCT_FIBONACCI64_MICRO) || defined(PRODUCT_FIBONACCI64_NANO) + writeAndCommitSettingsFib64(); + #elif defined(PRODUCT_FIBONACCI32) + writeAndCommitSettingsFib32(); #elif defined(PRODUCT_DEFAULT) writeAndCommitSettingsDefaultProduct(); #else @@ -1796,6 +1925,8 @@ void palettetest( CRGB* ledarray, uint16_t numleds, const CRGBPalette16& gCurren } +// TODO - swirlFibonacci(): Disable if NUM_PIXELS < 128? + #if IS_FIBONACCI // swirlFibonacci() uses physicalToFibonacci and angles void swirlFibonacci() { @@ -1827,6 +1958,8 @@ void swirlFibonacci() { } #endif +// TODO - fireFibonacci(): Disable if NUM_PIXELS < 128? + #if IS_FIBONACCI // fireFibonacci() uses coordsX/coordsY // TODO: combine with normal fire effect void fireFibonacci() { @@ -1841,6 +1974,8 @@ void fireFibonacci() { } #endif +// TODO - waterFibonacci(): Disable if NUM_PIXELS < 128? + #if IS_FIBONACCI // waterFibonacci() uses coordsX/coordsY // TODO: combine with normal water effect void waterFibonacci() { @@ -1855,6 +1990,8 @@ void waterFibonacci() { } #endif +// TODO - emitterFibonacci(): Disable if NUM_PIXELS < 128? + #if IS_FIBONACCI // emitterFibonacci() uses angle, antialiasPixelAR() /** * Emits arcs of color spreading out from the center to the edge of the disc. diff --git a/esp8266-fastled-webserver/include/configs/controller/controller_esp32.h b/esp8266-fastled-webserver/include/configs/controller/controller_esp32.h index 5810fa24..246ee964 100644 --- a/esp8266-fastled-webserver/include/configs/controller/controller_esp32.h +++ b/esp8266-fastled-webserver/include/configs/controller/controller_esp32.h @@ -23,7 +23,11 @@ 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 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..4e8c0689 --- /dev/null +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci32.h @@ -0,0 +1,64 @@ +/* + 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(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/fibonacci64.h b/esp8266-fastled-webserver/include/configs/product/fibonacci64.h new file mode 100644 index 00000000..5fc16d6b --- /dev/null +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci64.h @@ -0,0 +1,111 @@ +/* + 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(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/product_template.h b/esp8266-fastled-webserver/include/configs/product/product_template.h index d572b864..e10e9a8c 100644 --- a/esp8266-fastled-webserver/include/configs/product/product_template.h +++ b/esp8266-fastled-webserver/include/configs/product/product_template.h @@ -96,11 +96,14 @@ // // When this is true, the following must be defined in map.h: // -// const uint16_t physicalToFibonacci[NUM_PIXELS]; -// const uint16_t fibonacciToPhysical[NUM_PIXELS]; +// const uint8_t physicalToFibonacci[NUM_PIXELS]; +// const uint8_t fibonacciToPhysical[NUM_PIXELS]; // const uint8_t coordsX[NUM_PIXELS]; // const uint8_t coordsY[NUM_PIXELS]; // const uint8_t angles[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 From dd6ec3fbb5eec8a2dbd2e75857d16fcc1cde08ca Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Sun, 17 Oct 2021 23:24:29 -0700 Subject: [PATCH 04/16] Squashed commit of the combined_dev4: * Add support for Kraken64 * Fix some errors in, and improve perf of: * `setPixelAR()` * `andPixelAR()` * `antialiasPixelAR()` * Combine spiral clock functions. * Define `radiusProxy` as array alias. * Fix scaling for `radiusPalette()`. * Fix scaling for `radiusGradientPalette()`. --- esp8266-fastled-webserver/Map.h | 370 ++++++++++-------- esp8266-fastled-webserver/Noise.h | 7 +- esp8266-fastled-webserver/common.h | 11 +- esp8266-fastled-webserver/config.h | 12 +- .../esp8266-fastled-webserver.ino | 84 +++- .../include/configs/product/default.h | 3 + .../include/configs/product/fibonacci128.h | 3 + .../include/configs/product/fibonacci256.h | 3 + .../include/configs/product/fibonacci32.h | 3 + .../include/configs/product/fibonacci512.h | 3 + .../include/configs/product/fibonacci64.h | 3 + .../include/configs/product/kraken64.h | 92 +++++ .../configs/product/product_template.h | 25 +- 13 files changed, 427 insertions(+), 192 deletions(-) create mode 100644 esp8266-fastled-webserver/include/configs/product/kraken64.h diff --git a/esp8266-fastled-webserver/Map.h b/esp8266-fastled-webserver/Map.h index b9231b70..f77f12c7 100644 --- a/esp8266-fastled-webserver/Map.h +++ b/esp8266-fastled-webserver/Map.h @@ -1,4 +1,4 @@ -#if IS_FIBONACCI +#if IS_FIBONACCI || HAS_COORDINATE_MAP // Each Fibonacci board must define the following arrays: // @@ -72,27 +72,79 @@ #elif defined(PRODUCT_FIBONACCI64_FULL) || defined(PRODUCT_FIBONACCI64_MINI) const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 39, 52, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 51, 38, 25, 12, 4, 17, 30, 43, 56, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60 }; const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 39, 19, 58, 29, 9, 48, 20, 59, 38, 10, 49, 28, 1, 40, 18, 57, 30, 8, 47, 21, 60, 37, 11, 50, 27, 2, 41, 17, 56, 31, 7, 46, 22, 61, 36, 12, 51, 26, 3, 42, 16, 55, 32, 6, 45, 23, 62, 35, 13, 52, 25, 4, 43, 15, 54, 33, 5, 44, 24, 63, 34, 14, 53 }; - const uint8_t coordsX[NUM_PIXELS] { 140, 189, 208, 214, 208, 146, 168, 180, 180, 162, 152, 146, 129, 103, 72, 40, 70, 97, 120, 131, 107, 79, 50, 23, 0, 7, 23, 46, 76, 93, 57, 37, 28, 29, 87, 68, 59, 62, 80, 113, 91, 94, 109, 133, 202, 172, 145, 125, 117, 145, 170, 198, 227, 253, 255, 235, 210, 181, 148, 175, 207, 228, 240, 244 }; - const uint8_t coordsY[NUM_PIXELS] { 128, 114, 91, 63, 34, 0, 21, 48, 76, 106, 78, 47, 25, 11, 5, 38, 35, 42, 61, 101, 87, 69, 68, 78, 98, 143, 118, 102, 98, 122, 131, 152, 179, 209, 255, 230, 202, 174, 148, 142, 181, 210, 235, 252, 235, 234, 224, 203, 170, 183, 201, 205, 198, 181, 134, 157, 171, 173, 153, 145, 138, 120, 93, 63 }; - const uint8_t angles[NUM_PIXELS] { 0, 249, 241, 232, 223, 200, 208, 217, 226, 235, 212, 203, 194, 185, 176, 162, 171, 180, 188, 197, 174, 165, 156, 147, 139, 124, 133, 142, 151, 136, 128, 119, 110, 101, 78, 86, 95, 104, 113, 99, 90, 81, 72, 63, 40, 49, 58, 67, 75, 52, 43, 34, 25, 17, 2, 11, 20, 29, 38, 14, 6, 255, 246, 237 }; + const uint8_t coordsX[NUM_PIXELS] { 140, 189, 208, 214, 208, 146, 168, 180, 180, 162, 152, 146, 129, 103, 72, 40, 70, 97, 120, 131, 107, 79, 50, 23, 0, 7, 23, 46, 76, 93, 57, 37, 28, 29, 87, 68, 59, 62, 80, 113, 91, 94, 109, 133, 202, 172, 145, 125, 117, 145, 170, 198, 227, 253, 255, 235, 210, 181, 148, 175, 207, 228, 240, 244 }; + const uint8_t coordsY[NUM_PIXELS] { 128, 114, 91, 63, 34, 0, 21, 48, 76, 106, 78, 47, 25, 11, 5, 38, 35, 42, 61, 101, 87, 69, 68, 78, 98, 143, 118, 102, 98, 122, 131, 152, 179, 209, 255, 230, 202, 174, 148, 142, 181, 210, 235, 252, 235, 234, 224, 203, 170, 183, 201, 205, 198, 181, 134, 157, 171, 173, 153, 145, 138, 120, 93, 63 }; + const uint8_t angles[NUM_PIXELS] { 0, 249, 241, 232, 223, 200, 208, 217, 226, 235, 212, 203, 194, 185, 176, 162, 171, 180, 188, 197, 174, 165, 156, 147, 139, 124, 133, 142, 151, 136, 128, 119, 110, 101, 78, 86, 95, 104, 113, 99, 90, 81, 72, 63, 40, 49, 58, 67, 75, 52, 43, 34, 25, 17, 2, 11, 20, 29, 38, 14, 6, 255, 246, 237 }; #elif defined(PRODUCT_FIBONACCI32) - const uint8_t physicalToFibonacci[NUM_PIXELS] = { 0, 13, 26, 31, 18, 5, 10, 23, 28, 15, 2, 7, 20, 33, 25, 12, 4, 17, 30, 22, 9, 1, 14, 27, 32, 19, 6, 11, 24, 29, 16, 3, 8, 21 }; - const uint8_t fibonacciToPhysical[NUM_PIXELS] = { 0, 21, 10, 31, 16, 5, 26, 11, 32, 20, 6, 27, 15, 1, 22, 9, 30, 17, 4, 25, 12, 33, 19, 7, 28, 14, 2, 23, 8, 29, 18, 3, 24, 13 }; - const uint8_t coordsX[NUM_PIXELS] = { 152, 224, 252, 210, 211, 184, 169, 161, 89, 121, 138, 102, 61, 19, 13, 57, 82, 29, 0, 36, 63, 111, 79, 83, 158, 129, 118, 160, 196, 255, 212, 163, 203, 250 }; - const uint8_t coordsY[NUM_PIXELS] = { 120, 101, 69, 7, 48, 90, 50, 7, 0, 27, 83, 62, 37, 35, 84, 78, 112, 125, 154, 185, 149, 140, 195, 236, 255, 226, 179, 198, 223, 181, 183, 156, 144, 135 }; - const uint8_t angles[NUM_PIXELS] = { 255, 246, 237, 214, 223, 232, 208, 199, 176, 185, 193, 170, 161, 152, 138, 147, 132, 123, 114, 100, 108, 94, 85, 76, 53, 62, 70, 47, 38, 15, 23, 32, 9, 0 }; + const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 31, 18, 5, 10, 23, 28, 15, 2, 7, 20, 33, 25, 12, 4, 17, 30, 22, 9, 1, 14, 27, 32, 19, 6, 11, 24, 29, 16, 3, 8, 21 }; + const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 21, 10, 31, 16, 5, 26, 11, 32, 20, 6, 27, 15, 1, 22, 9, 30, 17, 4, 25, 12, 33, 19, 7, 28, 14, 2, 23, 8, 29, 18, 3, 24, 13 }; + const uint8_t coordsX[NUM_PIXELS] { 152, 224, 252, 210, 211, 184, 169, 161, 89, 121, 138, 102, 61, 19, 13, 57, 82, 29, 0, 36, 63, 111, 79, 83, 158, 129, 118, 160, 196, 255, 212, 163, 203, 250 }; + const uint8_t coordsY[NUM_PIXELS] { 120, 101, 69, 7, 48, 90, 50, 7, 0, 27, 83, 62, 37, 35, 84, 78, 112, 125, 154, 185, 149, 140, 195, 236, 255, 226, 179, 198, 223, 181, 183, 156, 144, 135 }; + const uint8_t angles[NUM_PIXELS] { 255, 246, 237, 214, 223, 232, 208, 199, 176, 185, 193, 170, 161, 152, 138, 147, 132, 123, 114, 100, 108, 94, 85, 76, 53, 62, 70, 47, 38, 15, 23, 32, 9, 0 }; +#elif defined(PRODUCT_KRAKEN64) + const uint8_t coordsX[NUM_PIXELS] { 151, 188, 199, 199, 171, 147, 131, 119, 124, 179, 200, 217, 237, 249, 242, 234, 255, 148, 175, 177, 150, 143, 171, 153, 155, 106, 110, 102, 75, 86, 106, 108, 88, 90, 84, 78, 107, 98, 121, 128, 80, 69, 134, 159, 192, 202, 195, 218, 61, 32, 18, 26, 39, 20, 3, 0, 48, 52, 61, 54, 33, 20, 7, 8 }; + const uint8_t coordsY[NUM_PIXELS] { 190, 204, 225, 252, 255, 236, 216, 191, 166, 147, 154, 170, 173, 156, 131, 107, 106, 148, 121, 86, 81, 63, 56, 36, 17, 145, 120, 96, 55, 23, 18, 0, 2, 112, 77, 31, 35, 49, 51, 30, 124, 103, 101, 98, 80, 58, 40, 69, 134, 124, 107, 81, 56, 43, 50, 70, 156, 180, 202, 219, 213, 195, 197, 215 }; + const uint8_t angles[NUM_PIXELS] { 0, 249, 241, 232, 223, 200, 208, 217, 226, 235, 212, 203, 194, 185, 176, 162, 171, 180, 188, 197, 174, 165, 156, 147, 139, 124, 133, 142, 151, 136, 128, 119, 110, 101, 78, 86, 95, 104, 113, 99, 90, 81, 72, 63, 40, 49, 58, 67, 75, 52, 43, 34, 25, 17, 2, 11, 20, 29, 38, 14, 6, 255, 246, 237 }; + const uint8_t body[NUM_PIXELS] { 0, 16, 32, 48, 64, 80, 96, 112, 128, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 255 }; + static_assert(NUM_PIXELS == ARRAY_SIZE2(body), ""); + // For reference purposes... + // const uint8_t head[9] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; + // const uint8_t tentacle0[8] { 9, 10, 11, 12, 13, 14, 15, 16 }; + // const uint8_t tentacle1[8] { 17, 18, 19, 20, 21, 22, 23, 24 }; + // const uint8_t tentacle2[8] { 25, 26, 27, 28, 29, 30, 31, 32 }; + // const uint8_t tentacle3[8] { 33, 34, 35, 36, 37, 38, 39 }; + // const uint8_t tentacle4[8] { 40, 41, 42, 43, 44, 45, 46, 47 }; + // const uint8_t tentacle5[8] { 48, 49, 50, 51, 52, 53, 54, 55 }; + // const uint8_t tentacle6[8] { 56, 57, 58, 59, 60, 61, 62, 63 }; #else #error "Unknown / Unsupported fibonacci product ... no mappings defined" #endif -static_assert(NUM_PIXELS == ARRAY_SIZE2(physicalToFibonacci), ""); -static_assert(NUM_PIXELS == ARRAY_SIZE2(fibonacciToPhysical), ""); -static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsX), ""); -static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsY), ""); -static_assert(NUM_PIXELS == ARRAY_SIZE2(angles), ""); -static const uint8_t RADII_SCALE_FACTOR { static_eval::value }; +#if IS_FIBONACCI + static_assert(NUM_PIXELS == ARRAY_SIZE2(physicalToFibonacci), ""); + static_assert(NUM_PIXELS == ARRAY_SIZE2(fibonacciToPhysical), ""); +#endif +#if HAS_COORDINATE_MAP + static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsX), ""); + static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsY), ""); + static_assert(NUM_PIXELS == ARRAY_SIZE2(angles), ""); +#endif +// What is HAS_RADIUS_PROXY? It could be the actual radius, or it could be something +// that is used "in place of" the radius during effects processing. +// Use reference to original array; avoids repeating preprocessor checks throughout the code.... +#if defined(PRODUCT_KRAKEN64) + #define HAS_RADIUS_PROXY 1 + static const auto (&radiusProxy)[NUM_PIXELS] = body; + static const uint8_t RADII_SCALE_DIVISOR { 1 }; // body[] values are already in range [0..255] + static const uint8_t RADII_SCALE_MULTIPLIER { 1 }; // body[] values are already in range [0..255] +#elif IS_FIBONACCI + #define HAS_RADIUS_PROXY 1 + + static const auto (&radiusProxy)[NUM_PIXELS] = physicalToFibonacci; + + static_assert( + ((NUM_PIXELS & (NUM_PIXELS-1)) == 0) || + (NUM_PIXELS == 34), + "RADII_SCALE_MULTIPLIER / RADII_SCALE_DIVISOR need updates to handle other non-power-of-two NUM_PIXELS" + ); + static const uint8_t RADII_SCALE_DIVISOR { (NUM_PIXELS <= 256u) ? 1 : (NUM_PIXELS / 256u) }; + static const uint8_t RADII_SCALE_MULTIPLIER { + (NUM_PIXELS >= 256) ? 1 : + (NUM_PIXELS == 34) ? 8 : // Careful .. use saturating multiplier or manually limit to 256... + ((NUM_PIXELS & (NUM_PIXELS-1)) == 0) ? (256u/NUM_PIXELS) : + 0 + }; + static_assert(RADII_SCALE_MULTIPLIER != 0, ""); +#else + #define HAS_RADIUS_PROXY 0 // default is that this is not supported.... +#endif +#if HAS_RADIUS_PROXY + static_assert(HAS_COORDINATE_MAP, "HAS_RADIUS_PROXY also requires coordinate map"); +#endif + +#if IS_FIBONACCI // drawSpiralLine() uses angles[] and physicalToFibonacci[] void drawSpiralLine(uint8_t angle, int step, CRGB color) { int startIndex = 0; @@ -121,76 +173,96 @@ void drawSpiralLine(uint8_t angle, int step, CRGB color) f = f - step; } } +#endif +#if HAS_RADIUS_PROXY // setPixelAR() uses radiusProxy[] +// given an angle and radius (and delta for both), set pixels that fall inside that range void setPixelAR(uint8_t angle, uint8_t dAngle, uint8_t radius, uint8_t dRadius, CRGB color) { - uint16_t amax = qadd8(angle, dAngle); - uint8_t amin = qsub8(angle, dAngle); - - uint16_t rmax = qadd8(radius, dRadius); - uint16_t rmin = qsub8(radius, dRadius); + uint8_t endRadius = qadd8(radius, dRadius); + uint8_t startRadius = qsub8(radius, dRadius); for (uint16_t i = 0; i < NUM_PIXELS; i++) { - uint8_t o = i; - - uint8_t ao = angles[o]; - - if (ao <= amax && ao >= amin) { - uint8_t ro = physicalToFibonacci[o]; - - if (ro <= rmax && ro >= rmin) { + // TODO: Change from pre-processor defines to `static const bool` values where possible + uint8_t ro = radiusProxy[i]; + // only mess with the pixel when it's radius is within the target radius + if (ro <= endRadius && ro >= startRadius) { + // Get pixel's angle (unit256) + uint8_t ao = angles[i]; + // set adiff to abs(ao - angle) ... relies on unsigned underflow resulting in larger value + uint8_t adiff = min(sub8(ao,angle), sub8(angle, ao)); + // only mess with the pixel when it's angle is within range of target + if (adiff <= dAngle) { leds[i] = color; } } } } +#endif +#if HAS_RADIUS_PROXY // andPixelAR() uses radiusProxy[] +// given an angle and radius (and delta for both), add color to pixels that fall inside that range void andPixelAR(uint8_t angle, uint8_t dAngle, uint8_t startRadius, uint8_t endRadius, CRGB color) { - uint16_t amax = qadd8(angle, dAngle); - uint8_t amin = qsub8(angle, dAngle); - for (uint16_t i = 0; i < NUM_PIXELS; i++) { - uint8_t o = i; - - uint8_t ao = angles[o]; - - if (ao <= amax && ao >= amin) { - uint8_t ro = physicalToFibonacci[o]; - - if (ro <= endRadius && ro >= startRadius) { + uint8_t ro = radiusProxy[i]; + // only mess with the pixel when it's radius is within the target radius + if (ro <= endRadius && ro >= startRadius) { + // Get pixel's angle (unit256) + uint8_t ao = angles[i]; + // set adiff to abs(ao - angle) ... relies on unsigned underflow resulting in larger value + uint8_t adiff = min(sub8(ao,angle), sub8(angle, ao)); + // only mess with the pixel when it's angle is within range of target + if (adiff <= dAngle) { leds[i] += color; } } } } +#endif +#if HAS_RADIUS_PROXY // antialiasPixelAR() uses angles[] and radiusProxy[] +// given an angle and radius (and delta for both), set pixels that fall inside that range, +// fading the color from full-color at center, to off (black) at the outer edges. void antialiasPixelAR(uint8_t angle, uint8_t dAngle, uint8_t startRadius, uint8_t endRadius, CRGB color, CRGB leds[] = leds, int _NUM_PIXELS = NUM_PIXELS) { + // NOTE: + // An earlier version of this routine had significant bugs. + // Do NOT use the version which does qsub8(max(...), min()), + // as it does not handle angle overflow well. + // This version does it properly: + // 1. subtract both ways + // 2. note that unsigned underlow will make the negative result really large instead + // 3. take smaller value + // This is the absolute offset from the target angle for (uint16_t i = 0; i < _NUM_PIXELS; i++) { - uint8_t o = i; - - uint8_t ao = angles[o]; - - uint8_t adiff = min(sub8(ao,angle), sub8(angle, ao)); - uint8_t fade = map(adiff, 0, dAngle, 0, 255); - CRGB faded = color; - faded.fadeToBlackBy(fade); - - if (adiff <= dAngle) { - uint8_t ro = physicalToFibonacci[o]; - - if (ro <= endRadius && ro >= startRadius) { + uint8_t ro = radiusProxy[i]; + // only mess with the pixel when it's radius is within the target radius + if (ro <= endRadius && ro >= startRadius) { + // Get pixel's angle (unit256) + uint8_t ao = angles[i]; + // set adiff to abs(ao - angle) ... relies on unsigned underflow resulting in larger value + uint8_t adiff = min(sub8(ao,angle), sub8(angle, ao)); + // only mess with the pixel when it's angle is within range of target + if (adiff <= dAngle) { + // map the intensity of the color so it fades to black at edge of allowed angle + uint8_t fade = map(adiff, 0, dAngle, 0, 255); + CRGB faded = color; + // fade the target color based on how far the angle was from the target + faded.fadeToBlackBy(fade); + // add the faded color (as an overlay) to existing colors leds[i] += faded; } } } } +#endif // TODO - anglePalette() from Fib32 sets `hues = 256 / NUM_PIXELS' ... which is ZERO(!) // The other similar functions are hard-coded to `hues = 1` even on Fib32. // Likely a bug in Fib32 branch for this one function? // Check if other branches did similar, or set to hard-coded value of 1? +#if HAS_COORDINATE_MAP // anglePalette() uses angles[] void anglePalette() { uint16_t hues = 1; @@ -200,16 +272,21 @@ void anglePalette() { leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - (x * hues)); } } +#endif +// TODO - consider adding pre-computed radii[], enabled anytime HAS_COORDINATE_MAP is true +#if HAS_RADIUS_PROXY // radiusPalette() uses radiusProxy[] void radiusPalette() { uint16_t hues = 1; for (uint16_t i = 0; i < NUM_PIXELS; i++) { - uint8_t r = physicalToFibonacci[i] / RADII_SCALE_FACTOR; + uint8_t r = ((unsigned)(radiusProxy[i] * RADII_SCALE_MULTIPLIER)) / RADII_SCALE_DIVISOR; leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - (r * hues)); } } +#endif +#if HAS_COORDINATE_MAP // xPalette() uses coordsX[] void xPalette() { uint16_t hues = 1; @@ -219,7 +296,9 @@ void xPalette() { leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - (x * hues)); } } +#endif +#if HAS_COORDINATE_MAP // yPalette() uses coordsY[] void yPalette() { uint16_t hues = 1; @@ -229,7 +308,9 @@ void yPalette() { leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - (y * hues)); } } +#endif +#if HAS_COORDINATE_MAP // xyPalette() uses coordsX[] and coordsY[] void xyPalette() { uint16_t hues = 1; @@ -240,7 +321,9 @@ void xyPalette() { leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - ((x + y) * hues)); } } +#endif +#if HAS_COORDINATE_MAP // angleGradientPalette() uses angles[] void angleGradientPalette() { uint16_t hues = 1; @@ -250,17 +333,20 @@ void angleGradientPalette() { leds[i] = ColorFromPalette(gCurrentPalette, beat8(speed) - (x * hues)); } } +#endif +#if HAS_RADIUS_PROXY // radiusGradientPalette() uses radiusProxy[] void radiusGradientPalette() { uint16_t hues = 1; for (uint16_t i = 0; i < NUM_PIXELS; i++) { - uint8_t r = physicalToFibonacci[i] / RADII_SCALE_FACTOR; - + uint8_t r = ((unsigned)(radiusProxy[i] * RADII_SCALE_MULTIPLIER)) / RADII_SCALE_DIVISOR; leds[i] = ColorFromPalette(gCurrentPalette, beat8(speed) - (r * hues)); } } +#endif +#if HAS_COORDINATE_MAP // xGradientPalette() uses coordsX[] void xGradientPalette() { uint16_t hues = 1; @@ -270,7 +356,9 @@ void xGradientPalette() { leds[i] = ColorFromPalette(gCurrentPalette, beat8(speed) - (x * hues)); } } +#endif +#if HAS_COORDINATE_MAP // yGradientPalette() uses coordsY[] void yGradientPalette() { uint16_t hues = 1; @@ -280,7 +368,9 @@ void yGradientPalette() { leds[i] = ColorFromPalette(gCurrentPalette, beat8(speed) - (y * hues)); } } +#endif +#if HAS_COORDINATE_MAP // xyGradientPalette() uses coordsX[] and coordsY[] void xyGradientPalette() { uint16_t hues = 1; @@ -291,41 +381,36 @@ void xyGradientPalette() { leds[i] = ColorFromPalette(gCurrentPalette, beat8(speed) - ((x + y) * hues)); } } +#endif -// TODO: Fib512 calculates the angles replacing `64` in EVERY_N_MILLIS() with `255`. -// Is this a bug in Fib512, or a bug in Fib256 and Fib128? - -// TODO: Fib64 has different hard-coded numbers within `drawAnalogClock()` also. -// It appears these *might* correspond to maximum radius to draw the corresponding -// hand for? If correct, the definition those magic numbers would need to be added -// to the product configuration section. - -// calls antialiasPixelAR, which requires physicalToFibonacci array) +#if IS_FIBONACCI // drawAnalogClock() calls antialiasPixelAR(), which requires physicalToFibonacci[] void drawAnalogClock() { - float second = timeClient.getSeconds(); - float minute = timeClient.getMinutes() + (second / 60.0); - float hour = timeClient.getHours() + (minute / 60.0); - const uint8_t hourRadius = 96; - const uint8_t minuteRadius = 192; - const uint8_t secondRadius = 255; + static_assert(NUM_PIXELS >= 32, "Update to drawAnalogClock() required to support fewer pixels"); + const uint8_t hourRadius = NUM_PIXELS / 8 * 3; // 96 designed for 256 pixels ==> 3/8 + const uint8_t minuteRadius = NUM_PIXELS / 4 * 3; // 192 designed for 256 pixels ==> 3/4 + const uint8_t secondRadius = NUM_PIXELS - 1; // 255 designed for 256 pixels ==> all pixels - const uint8_t hourHandWidth = 8; - const uint8_t minuteHandWidth = 7; - const uint8_t secondHandWidth = 6; + const uint8_t hourHandWidth = 8; // angle @ unit256 ~= 11.25000 degrees + const uint8_t minuteHandWidth = 7; // angle @ unit256 ~= 9.84375 degrees + const uint8_t secondHandWidth = 6; // angle @ unit256 ~= 8.43750 degrees - const float degreesPerSecond = 255.0 / 60.0; - const float degreesPerMinute = 255.0 / 60.0; - const float degreesPerHour = 255.0 / 12.0; + const float degreesPerSecond = 256.0 / 60.0; + const float degreesPerMinute = 256.0 / 60.0; + const float degreesPerHour = 256.0 / 12.0; - static uint8_t hourAngle = 255 - hour * degreesPerHour; - static uint8_t minuteAngle = 255 - minute * degreesPerMinute; - static uint8_t secondAngle = 255 - second * degreesPerSecond; + static uint8_t hourAngle = 0; + static uint8_t minuteAngle = 0; + static uint8_t secondAngle = 0; EVERY_N_MILLIS(100) { - hourAngle = 64 - hour * degreesPerHour; - minuteAngle = 64 - minute * degreesPerMinute; - secondAngle = 64 - second * degreesPerSecond; + float second = timeClient.getSeconds(); + float minute = timeClient.getMinutes() + (second / 60.0); + float hour = timeClient.getHours() + (minute / 60.0); + + hourAngle = 256u - hour * degreesPerHour; + minuteAngle = 256u - minute * degreesPerMinute; + secondAngle = 256u - second * degreesPerSecond; } fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); @@ -335,130 +420,71 @@ void drawAnalogClock() { antialiasPixelAR(hourAngle, hourHandWidth, 0, hourRadius, CRGB::Red ); leds[0] = CRGB::Red; } +#endif -// TODO: `drawSpiralAnalogClock()` -- review differences between the Fibonacci boards (e.g., hard-coded radii) - -// TODO: `drawSpiralAnalogClock()` -- Optimize more calculations within EVERY_N_MILLIS(100) - -// TODO: `drawSpiralAnalogClock()` -- config to disable the seconds hand? - -// TODO: `drawSpiralAnalogClock***()` -- disable all the below on boards with less than 128 pixels? - -void drawSpiralAnalogClock(uint8_t step) { - float second = timeClient.getSeconds(); - float minute = timeClient.getMinutes() + (second / 60.0); - float hour = timeClient.getHours() + (minute / 60.0); +// TODO: `drawSpiralAnalogClock13_21_and_34()` -- config to disable the seconds hand? +#if IS_FIBONACCI // drawSpiralAnalogClock*() calls drawSpiralLine(), which requires fibonacci +void drawSpiralAnalogClock(uint8_t step_h, uint8_t step_m, uint8_t step_s) { static uint8_t hourAngle = 0; static uint8_t minuteAngle = 0; static uint8_t secondAngle = 0; - const float degreesPerSecond = 255.0 / 60.0; - const float degreesPerMinute = 255.0 / 60.0; - const float degreesPerHour = 255.0 / 12.0; + const float degreesPerSecond = 256.0 / 60.0; + const float degreesPerMinute = 256.0 / 60.0; + const float degreesPerHour = 256.0 / 12.0; EVERY_N_MILLIS(100) { - hourAngle = 255 - hour * degreesPerHour; - minuteAngle = 255 - minute * degreesPerMinute; - secondAngle = 255 - second * degreesPerSecond; + float second = timeClient.getSeconds(); + float minute = timeClient.getMinutes() + (second / 60.0); + float hour = timeClient.getHours() + (minute / 60.0); + + hourAngle = 256u - hour * degreesPerHour; + minuteAngle = 256u - minute * degreesPerMinute; + secondAngle = 256u - second * degreesPerSecond; } - drawSpiralLine(secondAngle, step, CRGB(0, 0, 2)); - drawSpiralLine(minuteAngle, step, CRGB(0, 2, 0)); - drawSpiralLine(hourAngle, step, CRGB(2, 0, 0)); + drawSpiralLine(secondAngle, step_s, CRGB(0, 0, 2)); + drawSpiralLine(minuteAngle, step_m, CRGB(0, 2, 0)); + drawSpiralLine(hourAngle, step_h, CRGB(2, 0, 0)); +} +void drawSpiralAnalogClock(uint8_t step) { + drawSpiralAnalogClock(step, step, step); } - -// reduces pattern by clockBackgroundFade, then draws clock hands void drawSpiralAnalogClock13() { fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); - drawSpiralAnalogClock(13); + drawSpiralAnalogClock(13, 13, 13); } - void drawSpiralAnalogClock21() { fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); - drawSpiralAnalogClock(21); + drawSpiralAnalogClock(21, 21, 21); } - void drawSpiralAnalogClock34() { fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); - drawSpiralAnalogClock(34); + drawSpiralAnalogClock(34, 34, 34); } - void drawSpiralAnalogClock55() { fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); - drawSpiralAnalogClock(55); + drawSpiralAnalogClock(55, 55, 55); } - void drawSpiralAnalogClock89() { fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); - drawSpiralAnalogClock(89); + drawSpiralAnalogClock(89, 89, 89); } - void drawSpiralAnalogClock21and34() { fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); - drawSpiralAnalogClock(21); - drawSpiralAnalogClock(34); + drawSpiralAnalogClock(21, 21, 21); + drawSpiralAnalogClock(34, 34, 34); } - -// TODO: `drawSpiralAnalogClock13_21_and_34()` -- Optimize more calculations within EVERY_N_MILLIS(100) - -// TODO: `drawSpiralAnalogClock13_21_and_34()` -- config to disable the seconds hand? - -// TODO: `drawSpiralAnalogClock()` -- review differences between the Fibonacci boards (e.g., hard-coded radii) - void drawSpiralAnalogClock13_21_and_34() { - float second = timeClient.getSeconds(); - float minute = timeClient.getMinutes() + (second / 60.0); - float hour = timeClient.getHours() + (minute / 60.0); - - static uint8_t hourAngle = 0; - static uint8_t minuteAngle = 0; - static uint8_t secondAngle = 0; - - const float degreesPerSecond = 255.0 / 60.0; - const float degreesPerMinute = 255.0 / 60.0; - const float degreesPerHour = 255.0 / 12.0; - - EVERY_N_MILLIS(100) { - hourAngle = 255 - hour * degreesPerHour; - minuteAngle = 255 - minute * degreesPerMinute; - secondAngle = 255 - second * degreesPerSecond; - } - fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); - - drawSpiralLine(secondAngle, 13, CRGB(0, 0, 2)); - drawSpiralLine(minuteAngle, 21, CRGB(0, 2, 0)); - drawSpiralLine(hourAngle, 34, CRGB(2, 0, 0)); + drawSpiralAnalogClock(34, 21, 13); } - -// TODO: Optimize this so more calculations are within EVERY_N_MILLIS(100) -// TODO: Allow configuration to disable the seconds hand void drawSpiralAnalogClock34_21_and_13() { - float second = timeClient.getSeconds(); - float minute = timeClient.getMinutes() + (second / 60.0); - float hour = timeClient.getHours() + (minute / 60.0); - - static uint8_t hourAngle = 0; - static uint8_t minuteAngle = 0; - static uint8_t secondAngle = 0; - - const float degreesPerSecond = 255.0 / 60.0; - const float degreesPerMinute = 255.0 / 60.0; - const float degreesPerHour = 255.0 / 12.0; - - EVERY_N_MILLIS(100) { - hourAngle = 255 - hour * degreesPerHour; - minuteAngle = 255 - minute * degreesPerMinute; - secondAngle = 255 - second * degreesPerSecond; - } - fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); - - drawSpiralLine(secondAngle, 34, CRGB(0, 0, 2)); - drawSpiralLine(minuteAngle, 21, CRGB(0, 2, 0)); - drawSpiralLine(hourAngle, 13, CRGB(2, 0, 0)); + drawSpiralAnalogClock(13, 21, 34); } +#endif -#endif // IS_FIBONACCI +#endif // IS_FIBONACCI || HAS_COORDINATE_MAP diff --git a/esp8266-fastled-webserver/Noise.h b/esp8266-fastled-webserver/Noise.h index 23cc28f0..0f568d14 100644 --- a/esp8266-fastled-webserver/Noise.h +++ b/esp8266-fastled-webserver/Noise.h @@ -16,9 +16,8 @@ along with this program. If not, see . */ -// drawNoise() function uses coordsX / coordsY, which are only available for Fibonacci boards -#if IS_FIBONACCI - +// drawNoise() function uses coordsX / coordsY +#if HAS_COORDINATE_MAP // TODO: static assert that the values here correspond to the maximum storable value // used by the typeof(coordsX) and typeof(coordsY). @@ -201,4 +200,4 @@ void blackAndBlueNoise() { } -#endif // IS_FIBONACCI \ No newline at end of file +#endif // HAS_COORDINATE_MAP \ No newline at end of file diff --git a/esp8266-fastled-webserver/common.h b/esp8266-fastled-webserver/common.h index a2b5de7c..04b8bb25 100644 --- a/esp8266-fastled-webserver/common.h +++ b/esp8266-fastled-webserver/common.h @@ -84,9 +84,14 @@ extern String nameString; extern const uint8_t physicalToFibonacci [NUM_PIXELS]; extern const uint8_t fibonacciToPhysical [NUM_PIXELS]; #endif - extern const uint8_t coordsX[NUM_PIXELS]; - extern const uint8_t coordsY[NUM_PIXELS]; - extern const uint8_t angles[NUM_PIXELS]; +#elif defined(PRODUCT_KRAKEN64) + extern const uint8_t body [NUM_PIXELS]; +#endif + +#if HAS_COORDINATE_MAP + extern const uint8_t coordsX [NUM_PIXELS]; + extern const uint8_t coordsY [NUM_PIXELS]; + extern const uint8_t angles [NUM_PIXELS]; #endif // Structures diff --git a/esp8266-fastled-webserver/config.h b/esp8266-fastled-webserver/config.h index 733867d6..50bc7f57 100644 --- a/esp8266-fastled-webserver/config.h +++ b/esp8266-fastled-webserver/config.h @@ -24,7 +24,7 @@ // When compiling from Arduino, you can edit this file. // When compiling from PlatformIO, this is a reference for compiler flags. -#define PRODUCT_DEFAULT +// #define PRODUCT_DEFAULT // #define PRODUCT_FIBONACCI512 // #define PRODUCT_FIBONACCI256 // #define PRODUCT_FIBONACCI128 @@ -33,6 +33,8 @@ // #define PRODUCT_FIBONACCI64_MICRO // 40mm, WS2812C-2020, ~5mA/pixel // #define PRODUCT_FIBONACCI64_NANO // 33mm, SK6805-EC15, ~5mA/pixel // #define PRODUCT_FIBONACCI32 +#define PRODUCT_KRAKEN64 + // //////////////////////////////////////////////////////////////////////////////////////////////////// // Additional configuration options ... defaults shown @@ -49,6 +51,8 @@ // Product-specific configuration #if defined(PRODUCT_DEFAULT) #include "include\configs\product\default.h" + #elif defined(PRODUCT_KRAKEN64) + #include "include\configs\product\kraken64.h" #elif defined(PRODUCT_FIBONACCI32) #include "include\configs\product\fibonacci32.h" #elif defined(PRODUCT_FIBONACCI64_FULL) || defined(PRODUCT_FIBONACCI64_MINI) || defined(PRODUCT_FIBONACCI64_MICRO) || defined(PRODUCT_FIBONACCI64_NANO) @@ -126,6 +130,12 @@ #if !defined(IS_FIBONACCI) || ((IS_FIBONACCI != 0) && (IS_FIBONACCI != 1)) #error "IS_FIBONACCI must be defined to zero or one" #endif + #if !defined(HAS_COORDINATE_MAP) || ((HAS_COORDINATE_MAP != 0) && (HAS_COORDINATE_MAP != 1)) + #error "HAS_COORDINATE_MAP must be defined to zero or one" + #endif + #if IS_FIBONACCI && (!HAS_COORDINATE_MAP) + #error "IS_FIBONACCI is true, so HAS_COORDINATE_MAP must also be true (but is not)" + #endif #if !defined(PARALLEL_OUTPUT_CHANNELS) #error "PARALLEL_OUTPUT_CHANNELS must be defined" #elif (PARALLEL_OUTPUT_CHANNELS == 1) diff --git a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino index bfd5bd81..607b2965 100644 --- a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino +++ b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino @@ -137,7 +137,9 @@ PatternAndNameList patterns = { { pacifica_loop, "Pacifica" }, { pacifica_fibonacci_loop, "Pacifica Fibonacci" }, +#endif +#if IS_FIBONACCI || HAS_COORDINATE_MAP // matrix patterns { anglePalette, "Angle Palette" }, { radiusPalette, "Radius Palette" }, @@ -150,7 +152,9 @@ PatternAndNameList patterns = { { 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" }, @@ -163,7 +167,9 @@ PatternAndNameList patterns = { { oceanNoise, "Ocean Noise" }, { blackAndWhiteNoise, "Black & White Noise" }, { blackAndBlueNoise, "Black & Blue Noise" }, +#endif +#if IS_FIBONACCI { drawAnalogClock, "Analog Clock" }, { drawSpiralAnalogClock13, "Spiral Analog Clock 13" }, @@ -180,6 +186,12 @@ PatternAndNameList patterns = { { 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" }, @@ -1005,6 +1017,50 @@ void loop() { // TODO: Update magic number from 0x55 to 0xAA (or 0x96 or 0x69) +void readSettingsKraken64() +{ + // 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) { + return; + } + + brightness = EEPROM.read(0); + + currentPatternIndex = EEPROM.read(1); + if (currentPatternIndex >= patternCount) { + currentPatternIndex = patternCount - 1; + } + + byte r = EEPROM.read(2); + byte g = EEPROM.read(3); + byte b = EEPROM.read(4); + + if (r == 0 && g == 0 && b == 0) + { + } + else + { + solidColor = CRGB(r, g, b); + } + + power = EEPROM.read(5); + + autoplay = EEPROM.read(6); + autoplayDuration = EEPROM.read(7); + + currentPaletteIndex = EEPROM.read(8); + if (currentPaletteIndex >= paletteCount) { + currentPaletteIndex = paletteCount - 1; + } + + twinkleSpeed = EEPROM.read(9); + twinkleDensity = EEPROM.read(10); + + cooling = EEPROM.read(11); + sparking = EEPROM.read(12); +} void readSettingsFib32() { // check for "magic number" so we know settings have been written to EEPROM @@ -1280,7 +1336,9 @@ void readSettingsDefaultProduct() } void readSettings() { - #if defined(PRODUCT_FIBONACCI512) + #if defined(PRODUCT_KRAKEN64) + readSettingsKraken64(); + #elif defined(PRODUCT_FIBONACCI512) readSettingsFib512(); #elif defined(PRODUCT_FIBONACCI256) readSettingsFib256(); @@ -1297,6 +1355,25 @@ void readSettings() { #endif } +void writeAndCommitSettingsKraken64() +{ + EEPROM.write(0, brightness); + EEPROM.write(1, currentPatternIndex); + EEPROM.write(2, solidColor.r); + EEPROM.write(3, solidColor.g); + EEPROM.write(4, solidColor.b); + EEPROM.write(5, power); + EEPROM.write(6, autoplay); + EEPROM.write(7, autoplayDuration); + EEPROM.write(8, currentPaletteIndex); + EEPROM.write(9, twinkleSpeed); + EEPROM.write(10, twinkleDensity); + EEPROM.write(11, cooling); + EEPROM.write(12, sparking); + + EEPROM.write(511, 55); + EEPROM.commit(); +} void writeAndCommitSettingsFib32() { EEPROM.write(0, brightness); @@ -1392,7 +1469,6 @@ void writeAndCommitSettingsFib512() EEPROM.write(511, 55); EEPROM.commit(); } - void writeAndCommitSettingsDefaultProduct() { EEPROM.write(0, brightness); @@ -1415,7 +1491,9 @@ void writeAndCommitSettingsDefaultProduct() void writeAndCommitSettings() { - #if defined(PRODUCT_FIBONACCI512) + #if defined(PRODUCT_KRAKEN64) + writeAndCommitSettingsKraken64(); + #elif defined(PRODUCT_FIBONACCI512) writeAndCommitSettingsFib512(); #elif defined(PRODUCT_FIBONACCI256) writeAndCommitSettingsFib256(); diff --git a/esp8266-fastled-webserver/include/configs/product/default.h b/esp8266-fastled-webserver/include/configs/product/default.h index cb81478d..b3572fb4 100644 --- a/esp8266-fastled-webserver/include/configs/product/default.h +++ b/esp8266-fastled-webserver/include/configs/product/default.h @@ -56,6 +56,9 @@ #if !defined(IS_FIBONACCI) #define IS_FIBONACCI 0 #endif +#if !defined(HAS_COORDINATE_MAP) + #define HAS_COORDINATE_MAP 0 +#endif #if !defined(PARALLEL_OUTPUT_CHANNELS) #define PARALLEL_OUTPUT_CHANNELS 1 #endif diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci128.h b/esp8266-fastled-webserver/include/configs/product/fibonacci128.h index b366b288..d81f8afc 100644 --- a/esp8266-fastled-webserver/include/configs/product/fibonacci128.h +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci128.h @@ -56,6 +56,9 @@ #if !defined(IS_FIBONACCI) #define IS_FIBONACCI 1 #endif +#if !defined(HAS_COORDINATE_MAP) + #define HAS_COORDINATE_MAP 1 +#endif #if !defined(PARALLEL_OUTPUT_CHANNELS) #define PARALLEL_OUTPUT_CHANNELS 1 #endif diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci256.h b/esp8266-fastled-webserver/include/configs/product/fibonacci256.h index aa66389b..d0eda881 100644 --- a/esp8266-fastled-webserver/include/configs/product/fibonacci256.h +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci256.h @@ -56,6 +56,9 @@ #if !defined(IS_FIBONACCI) #define IS_FIBONACCI 1 #endif +#if !defined(HAS_COORDINATE_MAP) + #define HAS_COORDINATE_MAP 1 +#endif #if !defined(PARALLEL_OUTPUT_CHANNELS) #define PARALLEL_OUTPUT_CHANNELS 1 #endif diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci32.h b/esp8266-fastled-webserver/include/configs/product/fibonacci32.h index 4e8c0689..89b03062 100644 --- a/esp8266-fastled-webserver/include/configs/product/fibonacci32.h +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci32.h @@ -56,6 +56,9 @@ #if !defined(IS_FIBONACCI) #define IS_FIBONACCI 1 #endif +#if !defined(HAS_COORDINATE_MAP) + #define HAS_COORDINATE_MAP 1 +#endif #if !defined(PARALLEL_OUTPUT_CHANNELS) #define PARALLEL_OUTPUT_CHANNELS 1 #endif diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci512.h b/esp8266-fastled-webserver/include/configs/product/fibonacci512.h index a144a2ca..13067ea8 100644 --- a/esp8266-fastled-webserver/include/configs/product/fibonacci512.h +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci512.h @@ -56,6 +56,9 @@ #if !defined(IS_FIBONACCI) #define IS_FIBONACCI 1 #endif +#if !defined(HAS_COORDINATE_MAP) + #define HAS_COORDINATE_MAP 1 +#endif #if !defined(PARALLEL_OUTPUT_CHANNELS) #define PARALLEL_OUTPUT_CHANNELS 4 #endif diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci64.h b/esp8266-fastled-webserver/include/configs/product/fibonacci64.h index 5fc16d6b..78b42f8a 100644 --- a/esp8266-fastled-webserver/include/configs/product/fibonacci64.h +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci64.h @@ -103,6 +103,9 @@ #if !defined(IS_FIBONACCI) #define IS_FIBONACCI 1 #endif +#if !defined(HAS_COORDINATE_MAP) + #define HAS_COORDINATE_MAP 1 +#endif #if !defined(PARALLEL_OUTPUT_CHANNELS) #define PARALLEL_OUTPUT_CHANNELS 1 #endif 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..ab9beadb --- /dev/null +++ b/esp8266-fastled-webserver/include/configs/product/kraken64.h @@ -0,0 +1,92 @@ +/* + 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(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 index e10e9a8c..3634caba 100644 --- a/esp8266-fastled-webserver/include/configs/product/product_template.h +++ b/esp8266-fastled-webserver/include/configs/product/product_template.h @@ -87,20 +87,15 @@ #define PRODUCT_FRIENDLY_NAME "ESP8266 + FastLED" #endif -// IS_FIBONACCI is true when there are fibonacci-specific definitions for the product. -// TODO: Consider splitting to two variables: -// 1. HAS_LED_MAP -// Indicates existence of coordsX[], coordsY[] and angles[] -// 2. IS_FIBONACCI -// Implies HAS_LED_MAP, plus physicalToFibonacci[] and fibonacciToPhysical[] +// 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]; -// const uint8_t coordsX[NUM_PIXELS]; -// const uint8_t coordsY[NUM_PIXELS]; -// const uint8_t angles[NUM_PIXELS]; // // NOTE: physicalToFibonacci[] and fibonacciToPhysical[] are uint16_t when // NUM_PIXELS is greater than 256. @@ -108,6 +103,18 @@ #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 + // 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. From 43063d11a4ecb9f938b7f5b194401a19a353b808 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Mon, 18 Oct 2021 10:38:02 -0700 Subject: [PATCH 05/16] Add support for ESP8266 Thing --- esp8266-fastled-webserver/config.h | 13 +- .../esp8266-fastled-webserver.ino | 148 +++++++++++++++++- .../configs/controller/controller_esp8266.h | 8 +- .../include/configs/product/esp8266_thing.h | 118 ++++++++++++++ 4 files changed, 280 insertions(+), 7 deletions(-) create mode 100644 esp8266-fastled-webserver/include/configs/product/esp8266_thing.h diff --git a/esp8266-fastled-webserver/config.h b/esp8266-fastled-webserver/config.h index 50bc7f57..64b9f1f5 100644 --- a/esp8266-fastled-webserver/config.h +++ b/esp8266-fastled-webserver/config.h @@ -33,7 +33,8 @@ // #define PRODUCT_FIBONACCI64_MICRO // 40mm, WS2812C-2020, ~5mA/pixel // #define PRODUCT_FIBONACCI64_NANO // 33mm, SK6805-EC15, ~5mA/pixel // #define PRODUCT_FIBONACCI32 -#define PRODUCT_KRAKEN64 +// #define PRODUCT_KRAKEN64 +#define PRODUCT_ESP8266_THING // aka parallel (6-output) // //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -63,6 +64,8 @@ #include "include\configs\product\fibonacci256.h" #elif defined(PRODUCT_FIBONACCI512) #include "include\configs\product\fibonacci512.h" + #elif defined(PRODUCT_ESP8266_THING) // aka parallel + #include "include\configs\product\esp8266_thing.h" #else #error "Must define product to build against" #endif @@ -70,8 +73,10 @@ // Board-specific configuration #if defined(ARDUINO_ARCH_ESP32) #include "include\configs\controller\controller_esp32.h" - #else + #elif defined(ARDUINO_ARCH_ESP8266) #include "include\configs\controller\controller_esp8266.h" + #else + #error "Unknown board type ... currently only support ESP8266 and ESP32" #endif #endif @@ -142,8 +147,10 @@ // nothing to test here #elif (PARALLEL_OUTPUT_CHANNELS == 4) static_assert(NUM_PIXELS == (PIXELS_ON_DATA_PIN_1 + PIXELS_ON_DATA_PIN_2 + PIXELS_ON_DATA_PIN_3 + PIXELS_ON_DATA_PIN_4), ""); + #elif (PARALLEL_OUTPUT_CHANNELS == 6) + static_assert(NUM_PIXELS == (PIXELS_ON_DATA_PIN_1 + PIXELS_ON_DATA_PIN_2 + PIXELS_ON_DATA_PIN_3 + PIXELS_ON_DATA_PIN_4 + PIXELS_ON_DATA_PIN_5 + PIXELS_ON_DATA_PIN_6), ""); #else - #error "PARALLEL_OUTPUT_CHANNELS currently tested only with values 1 or 4." + #error "PARALLEL_OUTPUT_CHANNELS currently tested only with values 1, 4, or 6." #endif #if (UTC_OFFSET_IN_SECONDS < (-14L * 60L * 60L)) #error "UTC_OFFSET_IN_SECONDS offset does not appear correct (< -14H) ... Note it is defined in seconds." diff --git a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino index 607b2965..b7e90de4 100644 --- a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino +++ b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino @@ -127,7 +127,10 @@ PatternAndNameList patterns = { { colorWavesPlaygroundFibonacci, "Color Waves Playground Fibonacci" }, #endif - { wheel, "Wheel" }, + { wheel, "Wheel" }, +#if (PARALLEL_OUTPUT_CHANNELS > 1) + { multi_test, "Multi Test" }, +#endif #if IS_FIBONACCI { swirlFibonacci, "Swirl Fibonacci"}, @@ -278,6 +281,12 @@ constexpr int LedOffset() { #if PARALLEL_OUTPUT_CHANNELS >= 4 + ((ONE_BASED_OUTPUT_CHANNEL >= 4) ? PIXELS_ON_DATA_PIN_3 : 0) #endif + #if PARALLEL_OUTPUT_CHANNELS >= 5 + + ((ONE_BASED_OUTPUT_CHANNEL >= 5) ? PIXELS_ON_DATA_PIN_4 : 0) + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 6 + + ((ONE_BASED_OUTPUT_CHANNEL >= 6) ? PIXELS_ON_DATA_PIN_5 : 0) + #endif ; } template @@ -288,6 +297,12 @@ constexpr int LedCount() { return NUM_PIXELS; #else return // this would be much simpler with C++14 + #if PARALLEL_OUTPUT_CHANNELS >= 6 + (ONE_BASED_OUTPUT_CHANNEL == 6) ? PIXELS_ON_DATA_PIN_6 : + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 5 + (ONE_BASED_OUTPUT_CHANNEL == 5) ? PIXELS_ON_DATA_PIN_5 : + #endif #if PARALLEL_OUTPUT_CHANNELS >= 4 (ONE_BASED_OUTPUT_CHANNEL == 4) ? PIXELS_ON_DATA_PIN_4 : #endif @@ -327,6 +342,12 @@ void setup() { #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) @@ -1017,6 +1038,44 @@ void loop() { // TODO: Update magic number from 0x55 to 0xAA (or 0x96 or 0x69) +void readSettingsEsp8266Thing() // aka parallel +{ + // 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) { + return; + } + + brightness = EEPROM.read(0); + + currentPatternIndex = EEPROM.read(1); + if (currentPatternIndex >= patternCount) { + currentPatternIndex = patternCount - 1; + } + + byte r = EEPROM.read(2); + byte g = EEPROM.read(3); + byte b = EEPROM.read(4); + + if (r == 0 && g == 0 && b == 0) + { + } + else + { + solidColor = CRGB(r, g, b); + } + + power = EEPROM.read(5); + + autoplay = EEPROM.read(6); + autoplayDuration = EEPROM.read(7); + + currentPaletteIndex = EEPROM.read(8); + if (currentPaletteIndex >= paletteCount) { + currentPaletteIndex = paletteCount - 1; + } +} void readSettingsKraken64() { // check for "magic number" so we know settings have been written to EEPROM @@ -1336,7 +1395,9 @@ void readSettingsDefaultProduct() } void readSettings() { - #if defined(PRODUCT_KRAKEN64) + #if defined(PRODUCT_ESP8266_THING) + readSettingsEsp8266Thing(); + #elif defined(PRODUCT_KRAKEN64) readSettingsKraken64(); #elif defined(PRODUCT_FIBONACCI512) readSettingsFib512(); @@ -1355,6 +1416,25 @@ void readSettings() { #endif } +void writeAndCommitSettingsEsp8266Thing() // aka parallel +{ + EEPROM.write(0, brightness); + EEPROM.write(1, currentPatternIndex); + EEPROM.write(2, solidColor.r); + EEPROM.write(3, solidColor.g); + EEPROM.write(4, solidColor.b); + EEPROM.write(5, power); + EEPROM.write(6, autoplay); + EEPROM.write(7, autoplayDuration); + EEPROM.write(8, currentPaletteIndex); + EEPROM.write(9, twinkleSpeed); + EEPROM.write(10, twinkleDensity); + EEPROM.write(11, cooling); + EEPROM.write(12, sparking); + + EEPROM.write(511, 55); + EEPROM.commit(); +} void writeAndCommitSettingsKraken64() { EEPROM.write(0, brightness); @@ -1491,7 +1571,9 @@ void writeAndCommitSettingsDefaultProduct() void writeAndCommitSettings() { - #if defined(PRODUCT_KRAKEN64) + #if defined(PRODUCT_ESP8266_THING) + writeAndCommitSettingsEsp8266Thing(); + #elif defined(PRODUCT_KRAKEN64) writeAndCommitSettingsKraken64(); #elif defined(PRODUCT_FIBONACCI512) writeAndCommitSettingsFib512(); @@ -2119,3 +2201,63 @@ void wheel() { 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. + } else if (strip == 1) { + pixelOffset = LedOffset<2>(); // uses one-based indices... sigh. + pixelCount = LedCount<2>(); // uses one-based indices... sigh. + } else if (strip == 2) { + pixelOffset = LedOffset<3>(); // uses one-based indices... sigh. + pixelCount = LedCount<3>(); // uses one-based indices... sigh. + } else if (strip == 3) { + pixelOffset = LedOffset<4>(); // uses one-based indices... sigh. + pixelCount = LedCount<4>(); // uses one-based indices... sigh. + } else if (strip == 4) { + pixelOffset = LedOffset<5>(); // uses one-based indices... sigh. + pixelCount = LedCount<5>(); // uses one-based indices... sigh. + } else if (strip == 5) { + pixelOffset = LedOffset<6>(); // uses one-based indices... sigh. + pixelCount = LedCount<6>(); // uses one-based indices... sigh. + } 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 \ No newline at end of file diff --git a/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h b/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h index 74f8e050..69656fdf 100644 --- a/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h +++ b/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h @@ -20,7 +20,7 @@ #if !defined(ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP8266_H) #define ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP8266_H -static_assert(PARALLEL_OUTPUT_CHANNELS <= 4, "ESP8266 only supports four parallel outputs"); +static_assert(PARALLEL_OUTPUT_CHANNELS <= 6, "ESP8266 only supports four parallel outputs"); #if !defined(DATA_PIN) #if PARALLEL_OUTPUT_CHANNELS == 1 @@ -39,6 +39,12 @@ static_assert(PARALLEL_OUTPUT_CHANNELS <= 4, "ESP8266 only supports four paralle #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 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..87d3cb6e --- /dev/null +++ b/esp8266-fastled-webserver/include/configs/product/esp8266_thing.h @@ -0,0 +1,118 @@ +/* + 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(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 From bbad2582a58bb4125ed2f6fa652c9eedb32f54b1 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Mon, 18 Oct 2021 12:58:25 -0700 Subject: [PATCH 06/16] define the new product type -- no code yet --- esp8266-fastled-webserver/config.h | 6 +- .../include/configs/product/1628rings.h | 72 +++++++++++++++++++ .../include/configs/product/default.h | 3 + .../include/configs/product/esp8266_thing.h | 3 + .../include/configs/product/fibonacci128.h | 3 + .../include/configs/product/fibonacci256.h | 3 + .../include/configs/product/fibonacci32.h | 3 + .../include/configs/product/fibonacci512.h | 3 + .../include/configs/product/fibonacci64.h | 3 + .../include/configs/product/kraken64.h | 3 + .../configs/product/product_template.h | 7 ++ 11 files changed, 108 insertions(+), 1 deletion(-) create mode 100644 esp8266-fastled-webserver/include/configs/product/1628rings.h diff --git a/esp8266-fastled-webserver/config.h b/esp8266-fastled-webserver/config.h index 64b9f1f5..0e9a89a6 100644 --- a/esp8266-fastled-webserver/config.h +++ b/esp8266-fastled-webserver/config.h @@ -52,6 +52,8 @@ // Product-specific configuration #if defined(PRODUCT_DEFAULT) #include "include\configs\product\default.h" + #elif defined(PRODUCT_1628_RINGS) + #include "include\configs\product\1628rings.h" #elif defined(PRODUCT_KRAKEN64) #include "include\configs\product\kraken64.h" #elif defined(PRODUCT_FIBONACCI32) @@ -141,6 +143,9 @@ #if IS_FIBONACCI && (!HAS_COORDINATE_MAP) #error "IS_FIBONACCI is true, so HAS_COORDINATE_MAP must also be true (but is not)" #endif + #if !defined(HAS_POLAR_COORDS) || ((HAS_POLAR_COORDS != 0) && (HAS_POLAR_COORDS != 1)) + #error "HAS_POLAR_COORDS must be defined to zero or one" + #endif #if !defined(PARALLEL_OUTPUT_CHANNELS) #error "PARALLEL_OUTPUT_CHANNELS must be defined" #elif (PARALLEL_OUTPUT_CHANNELS == 1) @@ -160,7 +165,6 @@ #if (NTP_UPDATE_THROTTLE_MILLLISECONDS < (15UL * 1000UL)) #error "NTP_UPDATE_THROTTLE_MILLLISECONDS less than 15 seconds ... may exceed rate limits" #endif - #endif 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..6180cefe --- /dev/null +++ b/esp8266-fastled-webserver/include/configs/product/1628rings.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_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 0 +#endif +#if !defined(HAS_POLAR_COORDS) + #define HAS_POLAR_COORDS 1 +#endif +#if !defined(PARALLEL_OUTPUT_CHANNELS) + #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 index b3572fb4..abef6778 100644 --- a/esp8266-fastled-webserver/include/configs/product/default.h +++ b/esp8266-fastled-webserver/include/configs/product/default.h @@ -59,6 +59,9 @@ #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 diff --git a/esp8266-fastled-webserver/include/configs/product/esp8266_thing.h b/esp8266-fastled-webserver/include/configs/product/esp8266_thing.h index 87d3cb6e..4b9399fe 100644 --- a/esp8266-fastled-webserver/include/configs/product/esp8266_thing.h +++ b/esp8266-fastled-webserver/include/configs/product/esp8266_thing.h @@ -64,6 +64,9 @@ #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 diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci128.h b/esp8266-fastled-webserver/include/configs/product/fibonacci128.h index d81f8afc..923f8c1a 100644 --- a/esp8266-fastled-webserver/include/configs/product/fibonacci128.h +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci128.h @@ -59,6 +59,9 @@ #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 diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci256.h b/esp8266-fastled-webserver/include/configs/product/fibonacci256.h index d0eda881..488dc8b2 100644 --- a/esp8266-fastled-webserver/include/configs/product/fibonacci256.h +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci256.h @@ -59,6 +59,9 @@ #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 diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci32.h b/esp8266-fastled-webserver/include/configs/product/fibonacci32.h index 89b03062..d3415998 100644 --- a/esp8266-fastled-webserver/include/configs/product/fibonacci32.h +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci32.h @@ -59,6 +59,9 @@ #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 diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci512.h b/esp8266-fastled-webserver/include/configs/product/fibonacci512.h index 13067ea8..e72f204b 100644 --- a/esp8266-fastled-webserver/include/configs/product/fibonacci512.h +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci512.h @@ -59,6 +59,9 @@ #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 diff --git a/esp8266-fastled-webserver/include/configs/product/fibonacci64.h b/esp8266-fastled-webserver/include/configs/product/fibonacci64.h index 78b42f8a..89dd1715 100644 --- a/esp8266-fastled-webserver/include/configs/product/fibonacci64.h +++ b/esp8266-fastled-webserver/include/configs/product/fibonacci64.h @@ -106,6 +106,9 @@ #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 diff --git a/esp8266-fastled-webserver/include/configs/product/kraken64.h b/esp8266-fastled-webserver/include/configs/product/kraken64.h index ab9beadb..9a3d9b20 100644 --- a/esp8266-fastled-webserver/include/configs/product/kraken64.h +++ b/esp8266-fastled-webserver/include/configs/product/kraken64.h @@ -84,6 +84,9 @@ #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 diff --git a/esp8266-fastled-webserver/include/configs/product/product_template.h b/esp8266-fastled-webserver/include/configs/product/product_template.h index 3634caba..0d533b72 100644 --- a/esp8266-fastled-webserver/include/configs/product/product_template.h +++ b/esp8266-fastled-webserver/include/configs/product/product_template.h @@ -115,6 +115,13 @@ #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. From 8301100358dca209e71d55b02af23d922abac604 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Wed, 20 Oct 2021 16:56:13 -0700 Subject: [PATCH 07/16] Get 1628_RINGS product compiling --- PolarNoise.h | 26 +++ esp8266-fastled-webserver/Map.h | 144 +++++++++--- esp8266-fastled-webserver/Noise.h | 218 +++++++++++++++++- esp8266-fastled-webserver/config.h | 7 +- .../esp8266-fastled-webserver.ino | 92 +++++++- .../include/configs/product/1628rings.h | 5 +- 6 files changed, 427 insertions(+), 65 deletions(-) create mode 100644 PolarNoise.h diff --git a/PolarNoise.h b/PolarNoise.h new file mode 100644 index 00000000..3ddf4f28 --- /dev/null +++ b/PolarNoise.h @@ -0,0 +1,26 @@ +/* + Sol: https://github.com/evilgeniuslabs/sol + Copyright (C) 2016 Jason Coon, Evil Genius Labs + + 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 . +*/ + + + + + + + + +#endif // HAS_POLAR_COORDS \ No newline at end of file diff --git a/esp8266-fastled-webserver/Map.h b/esp8266-fastled-webserver/Map.h index f77f12c7..8c7bb03a 100644 --- a/esp8266-fastled-webserver/Map.h +++ b/esp8266-fastled-webserver/Map.h @@ -57,24 +57,36 @@ const uint8_t coordsX[NUM_PIXELS] { 170, 178, 185, 191, 196, 199, 202, 202, 202, 200, 196, 191, 184, 175, 161, 132, 148, 166, 176, 183, 188, 190, 192, 191, 190, 186, 182, 176, 170, 162, 153, 125, 136, 145, 154, 161, 168, 173, 177, 180, 181, 181, 178, 174, 167, 155, 139, 157, 164, 169, 170, 170, 168, 165, 160, 154, 147, 139, 129, 119, 109, 82, 93, 104, 114, 124, 132, 140, 147, 152, 157, 159, 160, 159, 155, 145, 145, 150, 150, 149, 146, 141, 135, 127, 119, 110, 100, 90, 79, 68, 57, 45, 56, 66, 77, 87, 97, 107, 115, 123, 130, 135, 139, 142, 141, 136, 134, 134, 131, 126, 120, 113, 105, 96, 86, 76, 66, 56, 45, 35, 25, 18, 27, 37, 47, 57, 67, 77, 86, 95, 104, 112, 119, 124, 128, 129, 125, 120, 113, 105, 97, 88, 78, 69, 59, 50, 40, 31, 22, 14, 6, 0, 6, 12, 19, 27, 35, 44, 54, 63, 73, 82, 91, 101, 109, 118, 121, 108, 98, 88, 78, 69, 59, 50, 41, 33, 25, 18, 12, 7, 3, 6, 8, 11, 15, 20, 26, 33, 40, 48, 57, 67, 77, 87, 98, 111, 102, 89, 77, 67, 58, 49, 41, 34, 28, 23, 19, 16, 15, 14, 15, 26, 24, 23, 24, 26, 28, 33, 38, 44, 51, 60, 69, 80, 93, 111, 100, 85, 73, 64, 55, 49, 43, 39, 36, 34, 33, 34, 36, 39, 43, 58, 53, 49, 45, 44, 43, 44, 46, 50, 55, 61, 69, 79, 93, 116, 104, 87, 76, 68, 62, 58, 55, 54, 54, 55, 58, 62, 68, 74, 82, 108, 99, 90, 83, 77, 72, 68, 65, 64, 65, 67, 70, 76, 85, 97, 112, 94, 85, 80, 76, 75, 75, 77, 81, 85, 91, 98, 106, 115, 125, 153, 142, 131, 122, 113, 105, 99, 93, 89, 87, 85, 86, 89, 95, 106, 123, 105, 99, 96, 96, 98, 101, 106, 112, 119, 128, 137, 147, 157, 168, 180, 193, 182, 171, 161, 151, 141, 133, 125, 118, 113, 108, 106, 106, 108, 115, 116, 114, 115, 118, 123, 129, 137, 145, 154, 164, 174, 184, 195, 206, 216, 226, 216, 205, 195, 185, 175, 165, 156, 147, 139, 133, 127, 123, 121, 124, 127, 129, 134, 141, 148, 156, 165, 174, 184, 194, 204, 214, 224, 233, 242, 253, 246, 238, 229, 221, 211, 202, 192, 182, 173, 164, 155, 147, 140, 133, 134, 142, 151, 160, 169, 179, 188, 198, 207, 216, 225, 233, 241, 247, 253, 255, 251, 247, 241, 234, 227, 219, 210, 201, 192, 182, 173, 163, 153, 142, 134, 151, 163, 174, 184, 194, 203, 212, 220, 227, 233, 239, 243, 247, 249, 242, 242, 241, 238, 235, 230, 225, 218, 211, 203, 194, 184, 173, 161, 146, 155, 170, 182, 192, 201, 208, 215, 221, 226, 229, 231, 232, 232, 231, 228, 215, 219, 221, 223, 223, 221, 219, 215, 210, 204, 197, 188, 177, 164, 144, 154, 170, 182, 191, 198, 204, 208, 211, 212, 213, 212, 209, 205, 200, 194 }; const uint8_t coordsY[NUM_PIXELS] { 6, 14, 22, 31, 41, 50, 60, 70, 80, 89, 98, 106, 114, 120, 125, 128, 124, 116, 109, 101, 92, 82, 73, 63, 54, 44, 35, 27, 18, 11, 4, 0, 5, 10, 17, 24, 32, 40, 49, 59, 68, 78, 87, 97, 106, 116, 121, 106, 95, 85, 75, 65, 56, 47, 38, 31, 24, 17, 12, 7, 4, 10, 10, 13, 16, 20, 25, 31, 39, 46, 55, 64, 74, 85, 96, 111, 101, 87, 76, 65, 56, 48, 41, 34, 29, 25, 21, 20, 19, 19, 21, 33, 30, 29, 28, 29, 31, 34, 39, 45, 51, 59, 69, 79, 92, 111, 101, 85, 73, 64, 56, 50, 45, 41, 39, 38, 38, 40, 43, 47, 52, 68, 62, 56, 53, 50, 49, 49, 50, 53, 57, 63, 70, 80, 94, 119, 106, 89, 78, 70, 65, 61, 59, 59, 60, 62, 66, 71, 77, 84, 92, 119, 109, 100, 92, 85, 80, 75, 72, 70, 70, 71, 74, 79, 87, 99, 114, 97, 88, 83, 81, 80, 81, 84, 88, 94, 100, 108, 116, 126, 136, 163, 152, 142, 132, 123, 114, 107, 101, 96, 93, 91, 91, 93, 98, 108, 108, 102, 101, 101, 104, 108, 114, 120, 128, 137, 146, 157, 167, 178, 190, 203, 192, 181, 170, 160, 150, 141, 133, 126, 119, 115, 111, 110, 111, 118, 119, 118, 120, 124, 130, 136, 144, 153, 162, 172, 182, 193, 203, 214, 224, 232, 223, 213, 202, 192, 182, 172, 163, 154, 146, 139, 132, 128, 125, 126, 129, 133, 139, 146, 154, 162, 172, 181, 191, 201, 210, 220, 229, 238, 246, 255, 249, 242, 234, 225, 216, 207, 197, 188, 178, 169, 160, 151, 143, 136, 135, 145, 155, 164, 174, 183, 193, 202, 211, 220, 228, 236, 243, 249, 254, 253, 250, 246, 242, 236, 229, 222, 213, 205, 196, 186, 176, 166, 155, 143, 133, 153, 166, 177, 187, 196, 205, 214, 221, 228, 234, 238, 242, 245, 246, 246, 236, 237, 237, 236, 233, 229, 225, 219, 212, 204, 195, 186, 175, 162, 146, 156, 171, 182, 192, 201, 208, 214, 220, 223, 226, 228, 228, 227, 224, 221, 207, 211, 215, 217, 218, 218, 216, 213, 209, 203, 196, 187, 177, 164, 142, 153, 170, 181, 190, 196, 201, 205, 207, 208, 207, 205, 202, 197, 191, 184, 159, 168, 176, 182, 188, 192, 195, 197, 197, 196, 193, 189, 182, 173, 160, 146, 164, 173, 180, 184, 186, 186, 185, 183, 179, 174, 167, 160, 151, 142, 114, 125, 135, 144, 152, 159, 165, 170, 173, 175, 176, 174, 171, 164, 153, 136, 154, 161, 164, 165, 164, 162, 157, 152, 145, 138, 129, 119, 109, 98, 72, 83, 94, 105, 114, 124, 132, 139, 145, 150, 153, 155, 155, 152, 143, 142, 146, 146, 143, 139, 134, 127, 119, 110, 101, 91, 81, 70, 59, 48, 37, 48, 58, 69, 79, 89, 99, 108, 116, 123, 129, 134, 137, 138, 134, 132, 130, 126, 121, 114, 106, 98, 88, 79, 69, 59, 48, 38, 29, 19 }; const uint8_t angles[NUM_PIXELS] { 205, 208, 211, 215, 218, 221, 225, 228, 231, 235, 238, 242, 245, 248, 252, 255, 246, 243, 239, 236, 233, 229, 226, 223, 219, 216, 213, 209, 206, 203, 199, 190, 194, 197, 200, 204, 207, 211, 214, 217, 221, 224, 227, 231, 234, 237, 232, 229, 225, 222, 219, 215, 212, 208, 205, 202, 198, 195, 192, 188, 185, 176, 180, 183, 186, 190, 193, 196, 200, 203, 206, 210, 213, 216, 220, 223, 214, 211, 208, 204, 201, 198, 194, 191, 188, 184, 181, 177, 174, 171, 167, 162, 165, 169, 172, 175, 179, 182, 185, 189, 192, 196, 199, 202, 206, 209, 200, 197, 193, 190, 187, 183, 180, 177, 173, 170, 167, 163, 160, 157, 153, 148, 151, 154, 158, 161, 165, 168, 171, 175, 178, 181, 185, 188, 191, 195, 186, 183, 179, 176, 173, 169, 166, 162, 159, 156, 152, 149, 146, 142, 139, 130, 133, 137, 140, 144, 147, 150, 154, 157, 160, 164, 167, 170, 174, 177, 172, 168, 165, 162, 158, 155, 152, 148, 145, 141, 138, 135, 131, 128, 125, 116, 119, 123, 126, 129, 133, 136, 139, 143, 146, 149, 153, 156, 160, 163, 154, 151, 147, 144, 141, 137, 134, 131, 127, 124, 121, 117, 114, 110, 107, 102, 105, 108, 112, 115, 118, 122, 125, 129, 132, 135, 139, 142, 145, 149, 140, 137, 133, 130, 126, 123, 120, 116, 113, 110, 106, 103, 100, 96, 93, 87, 91, 94, 98, 101, 104, 108, 111, 114, 118, 121, 124, 128, 131, 134, 126, 122, 119, 116, 112, 109, 106, 102, 99, 95, 92, 89, 85, 82, 79, 70, 73, 77, 80, 83, 87, 90, 93, 97, 100, 103, 107, 110, 114, 117, 111, 108, 105, 101, 98, 95, 91, 88, 85, 81, 78, 74, 71, 68, 64, 56, 59, 62, 66, 69, 72, 76, 79, 82, 86, 89, 93, 96, 99, 103, 97, 94, 90, 87, 84, 80, 77, 74, 70, 67, 64, 60, 57, 54, 50, 47, 41, 45, 48, 51, 55, 58, 62, 65, 68, 72, 75, 78, 82, 85, 88, 80, 76, 73, 70, 66, 63, 59, 56, 53, 49, 46, 43, 39, 36, 33, 27, 31, 34, 37, 41, 44, 47, 51, 54, 57, 61, 64, 67, 71, 74, 65, 62, 59, 55, 52, 49, 45, 42, 39, 35, 32, 28, 25, 22, 18, 10, 13, 16, 20, 23, 26, 30, 33, 36, 40, 43, 47, 50, 53, 57, 51, 48, 44, 41, 38, 34, 31, 28, 24, 21, 18, 14, 11, 8, 4, 251, 254, 2, 5, 9, 12, 16, 19, 22, 26, 29, 32, 36, 39, 42, 37, 34, 30, 27, 24, 20, 17, 13, 10, 7, 3, 0, 252, 249, 245, 236, 240, 243, 247, 250, 253, 1, 5, 8, 11, 15, 18, 21, 25, 28, 19, 16, 13, 9, 6, 3, 255, 251, 248, 244, 241, 238, 234, 231, 228, 222, 226, 229, 232, 236, 239, 242, 246, 249, 252, 0, 4, 7, 11, 14, 5, 2, 254, 250, 247, 244, 240, 237, 234, 230, 227, 223, 220, 217, 213 }; + static const auto (&radiusProxy)[NUM_PIXELS] = physicalToFibonacci; + static const uint8_t RADII_SCALE_DIVISOR { 2 }; + static const uint8_t RADII_SCALE_MULTIPLIER { 1 }; #elif defined(PRODUCT_FIBONACCI256) const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 39, 52, 65, 78, 91, 104, 117, 130, 143, 156, 169, 182, 195, 208, 221, 234, 247, 252, 239, 226, 213, 200, 187, 174, 161, 148, 135, 122, 109, 96, 83, 70, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 75, 88, 101, 114, 127, 140, 153, 166, 179, 192, 205, 218, 231, 244, 249, 236, 223, 210, 197, 184, 171, 158, 145, 132, 119, 106, 93, 80, 67, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189, 202, 215, 228, 241, 254, 246, 233, 220, 207, 194, 181, 168, 155, 142, 129, 116, 103, 90, 77, 64, 51, 38, 25, 12, 4, 17, 30, 43, 56, 69, 82, 95, 108, 121, 134, 147, 160, 173, 186, 199, 212, 225, 238, 251, 243, 230, 217, 204, 191, 178, 165, 152, 139, 126, 113, 100, 87, 74, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 66, 79, 92, 105, 118, 131, 144, 157, 170, 183, 196, 209, 222, 235, 248, 253, 240, 227, 214, 201, 188, 175, 162, 149, 136, 123, 110, 97, 84, 71, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 76, 89, 102, 115, 128, 141, 154, 167, 180, 193, 206, 219, 232, 245, 250, 237, 224, 211, 198, 185, 172, 159, 146, 133, 120, 107, 94, 81, 68, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60, 73, 86, 99, 112, 125, 138, 151, 164, 177, 190, 203, 216, 229, 242, 255 }; const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 157, 78, 235, 118, 39, 196, 79, 236, 156, 40, 197, 117, 1, 158, 77, 234, 119, 38, 195, 80, 237, 155, 41, 198, 116, 2, 159, 76, 233, 120, 37, 194, 81, 238, 154, 42, 199, 115, 3, 160, 75, 232, 121, 36, 193, 82, 239, 153, 43, 200, 114, 4, 161, 74, 231, 122, 35, 192, 83, 240, 152, 44, 201, 113, 5, 162, 73, 230, 123, 34, 191, 84, 241, 151, 45, 202, 112, 6, 163, 72, 229, 124, 33, 190, 85, 242, 150, 46, 203, 111, 7, 164, 71, 228, 125, 32, 189, 86, 243, 149, 47, 204, 110, 8, 165, 70, 227, 126, 31, 188, 87, 244, 148, 48, 205, 109, 9, 166, 69, 226, 127, 30, 187, 88, 245, 147, 49, 206, 108, 10, 167, 68, 225, 128, 29, 186, 89, 246, 146, 50, 207, 107, 11, 168, 67, 224, 129, 28, 185, 90, 247, 145, 51, 208, 106, 12, 169, 66, 223, 130, 27, 184, 91, 248, 144, 52, 209, 105, 13, 170, 65, 222, 131, 26, 183, 92, 249, 143, 53, 210, 104, 14, 171, 64, 221, 132, 25, 182, 93, 250, 142, 54, 211, 103, 15, 172, 63, 220, 133, 24, 181, 94, 251, 141, 55, 212, 102, 16, 173, 62, 219, 134, 23, 180, 95, 252, 140, 56, 213, 101, 17, 174, 61, 218, 135, 22, 179, 96, 253, 139, 57, 214, 100, 18, 175, 60, 217, 136, 21, 178, 97, 254, 138, 58, 215, 99, 19, 176, 59, 216, 137, 20, 177, 98, 255 }; const uint8_t coordsX[NUM_PIXELS] { 133, 156, 165, 168, 165, 158, 147, 132, 114, 95, 76, 57, 41, 28, 19, 15, 17, 24, 37, 56, 123, 96, 73, 53, 38, 28, 24, 25, 31, 41, 55, 71, 89, 106, 122, 136, 146, 152, 152, 143, 138, 136, 128, 115, 101, 85, 70, 56, 44, 37, 33, 34, 41, 53, 69, 90, 114, 140, 167, 226, 204, 180, 154, 129, 106, 85, 67, 54, 46, 43, 44, 50, 60, 72, 86, 100, 113, 123, 128, 117, 104, 90, 78, 67, 59, 54, 54, 59, 68, 82, 100, 121, 143, 167, 191, 212, 231, 246, 255, 251, 251, 245, 233, 218, 199, 178, 156, 134, 114, 96, 82, 73, 67, 66, 70, 78, 89, 103, 111, 94, 84, 80, 81, 86, 96, 109, 126, 145, 165, 185, 204, 220, 233, 241, 244, 241, 232, 217, 179, 201, 217, 229, 235, 235, 230, 220, 207, 190, 172, 154, 136, 121, 108, 99, 95, 96, 104, 120, 110, 111, 118, 130, 144, 160, 176, 192, 206, 217, 224, 227, 224, 216, 202, 184, 162, 137, 110, 44, 68, 94, 120, 145, 168, 187, 202, 212, 216, 216, 212, 203, 191, 177, 162, 148, 135, 126, 122, 136, 147, 161, 174, 186, 197, 204, 206, 205, 198, 187, 172, 152, 130, 106, 81, 58, 36, 17, 0, 5, 15, 30, 49, 71, 93, 116, 138, 157, 173, 185, 192, 195, 193, 187, 178, 166, 152, 137, 149, 164, 175, 180, 182, 179, 171, 159, 143, 125, 105, 83, 63, 44, 28, 16, 9, 7, 12, 23 }; const uint8_t coordsY[NUM_PIXELS] { 126, 120, 109, 96, 82, 69, 57, 49, 45, 45, 50, 59, 74, 92, 114, 138, 163, 188, 211, 231, 255, 248, 235, 218, 198, 175, 152, 129, 107, 89, 74, 63, 57, 56, 59, 66, 76, 88, 102, 116, 103, 88, 77, 71, 68, 70, 77, 88, 103, 121, 141, 163, 184, 205, 222, 236, 245, 249, 247, 208, 224, 235, 241, 240, 234, 223, 209, 191, 172, 152, 132, 115, 101, 90, 84, 82, 86, 95, 114, 107, 98, 98, 103, 112, 126, 142, 159, 177, 195, 210, 222, 230, 233, 230, 223, 209, 191, 168, 142, 98, 125, 151, 174, 194, 209, 219, 223, 223, 218, 208, 195, 180, 164, 148, 134, 122, 114, 112, 123, 128, 138, 151, 165, 180, 193, 203, 211, 214, 212, 206, 194, 178, 158, 134, 109, 83, 58, 35, 11, 28, 48, 71, 95, 120, 142, 163, 179, 192, 200, 203, 202, 196, 187, 175, 162, 148, 136, 133, 152, 166, 177, 186, 190, 191, 187, 178, 165, 148, 128, 107, 84, 62, 41, 24, 11, 2, 0, 28, 16, 9, 8, 13, 23, 37, 55, 75, 96, 116, 135, 151, 164, 173, 177, 177, 172, 162, 146, 153, 161, 163, 160, 152, 139, 124, 106, 87, 69, 51, 36, 25, 18, 16, 20, 29, 44, 64, 133, 106, 81, 60, 44, 32, 26, 25, 29, 38, 50, 65, 82, 99, 115, 129, 140, 147, 148, 138, 134, 131, 122, 110, 95, 80, 65, 52, 42, 36, 34, 37, 45, 59, 77, 98, 123, 149, 176, 202 }; const uint8_t angles[NUM_PIXELS] { 0, 247, 238, 229, 220, 211, 203, 194, 185, 176, 167, 159, 150, 141, 132, 123, 115, 106, 97, 88, 65, 74, 83, 92, 100, 109, 118, 127, 136, 144, 153, 162, 171, 180, 188, 197, 206, 215, 224, 232, 209, 201, 192, 183, 174, 165, 157, 148, 139, 130, 121, 113, 104, 95, 86, 77, 69, 60, 51, 28, 37, 46, 54, 63, 72, 81, 90, 98, 107, 116, 125, 134, 142, 151, 160, 169, 178, 186, 195, 172, 163, 155, 146, 137, 128, 119, 111, 102, 93, 84, 75, 67, 58, 49, 40, 31, 23, 14, 5, 246, 255, 8, 17, 26, 35, 44, 52, 61, 70, 79, 88, 96, 105, 114, 123, 132, 140, 149, 135, 126, 117, 108, 100, 91, 82, 73, 64, 56, 47, 38, 29, 20, 12, 3, 250, 241, 232, 223, 209, 218, 227, 235, 244, 253, 6, 15, 24, 33, 41, 50, 59, 68, 77, 85, 94, 103, 112, 98, 89, 80, 71, 62, 54, 45, 36, 27, 18, 10, 1, 247, 239, 230, 221, 212, 203, 195, 186, 163, 172, 180, 189, 198, 207, 216, 224, 233, 242, 251, 4, 13, 22, 31, 39, 48, 57, 66, 75, 52, 43, 34, 25, 16, 8, 254, 245, 237, 228, 219, 210, 201, 193, 184, 175, 166, 157, 149, 126, 134, 143, 152, 161, 170, 178, 187, 196, 205, 214, 222, 231, 240, 249, 2, 11, 20, 28, 37, 14, 5, 252, 243, 235, 226, 217, 208, 199, 191, 182, 173, 164, 155, 147, 138, 129, 120, 111, 103 }; + static const auto (&radiusProxy)[NUM_PIXELS] = physicalToFibonacci; + static const uint8_t RADII_SCALE_DIVISOR { 1 }; + static const uint8_t RADII_SCALE_MULTIPLIER { 1 }; #elif defined(PRODUCT_FIBONACCI128) const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 39, 52, 65, 78, 91, 104, 117, 122, 109, 96, 83, 70, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 75, 88, 101, 114, 127, 119, 106, 93, 80, 67, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 116, 103, 90, 77, 64, 51, 38, 25, 12, 4, 17, 30, 43, 56, 69, 82, 95, 108, 121, 126, 113, 100, 87, 74, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 66, 79, 92, 105, 118, 123, 110, 97, 84, 71, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 76, 89, 102, 115, 120, 107, 94, 81, 68, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60, 73, 86, 99, 112, 125 }; const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 79, 39, 117, 59, 19, 98, 40, 118, 78, 20, 99, 58, 1, 80, 38, 116, 60, 18, 97, 41, 119, 77, 21, 100, 57, 2, 81, 37, 115, 61, 17, 96, 42, 120, 76, 22, 101, 56, 3, 82, 36, 114, 62, 16, 95, 43, 121, 75, 23, 102, 55, 4, 83, 35, 113, 63, 15, 94, 44, 122, 74, 24, 103, 54, 5, 84, 34, 112, 64, 14, 93, 45, 123, 73, 25, 104, 53, 6, 85, 33, 111, 65, 13, 92, 46, 124, 72, 26, 105, 52, 7, 86, 32, 110, 66, 12, 91, 47, 125, 71, 27, 106, 51, 8, 87, 31, 109, 67, 11, 90, 48, 126, 70, 28, 107, 50, 9, 88, 30, 108, 68, 10, 89, 49, 127, 69, 29 }; const uint8_t coordsX[NUM_PIXELS] { 137, 170, 182, 186, 182, 172, 156, 135, 110, 83, 26, 49, 74, 99, 121, 141, 155, 164, 164, 151, 145, 141, 129, 112, 91, 69, 47, 27, 11, 0, 9, 11, 19, 33, 50, 70, 90, 108, 123, 130, 114, 96, 77, 58, 43, 32, 25, 25, 32, 45, 85, 65, 51, 43, 42, 47, 58, 74, 94, 105, 81, 68, 62, 63, 70, 84, 103, 127, 154, 218, 193, 167, 142, 119, 101, 89, 83, 84, 96, 118, 104, 106, 116, 132, 152, 175, 198, 221, 241, 255, 248, 236, 219, 199, 178, 158, 140, 126, 121, 140, 157, 176, 195, 213, 227, 237, 241, 239, 193, 210, 221, 225, 222, 214, 201, 184, 164, 142, 160, 181, 196, 204, 206, 202, 191, 174, 152, 125 }; const uint8_t coordsY[NUM_PIXELS] { 130, 121, 105, 86, 66, 47, 31, 19, 13, 13, 55, 39, 30, 28, 33, 43, 57, 75, 95, 115, 96, 75, 60, 50, 46, 49, 59, 74, 96, 122, 166, 139, 114, 93, 78, 69, 67, 72, 85, 112, 102, 90, 89, 96, 110, 129, 152, 177, 203, 227, 247, 228, 207, 184, 161, 140, 123, 112, 109, 126, 132, 146, 165, 185, 206, 225, 240, 251, 255, 224, 235, 240, 237, 229, 216, 199, 181, 161, 143, 139, 166, 186, 202, 215, 221, 222, 216, 204, 185, 115, 142, 166, 184, 197, 203, 202, 195, 181, 158, 167, 180, 182, 178, 166, 148, 126, 101, 74, 21, 42, 66, 91, 114, 134, 150, 159, 160, 147, 141, 137, 124, 106, 85, 63, 42, 24, 9, 0 }; const uint8_t angles[NUM_PIXELS] { 0, 247, 239, 230, 221, 212, 203, 194, 186, 177, 154, 163, 171, 180, 189, 198, 207, 216, 224, 233, 210, 201, 192, 184, 175, 166, 157, 148, 139, 131, 116, 125, 134, 143, 152, 160, 169, 178, 187, 196, 173, 164, 155, 146, 137, 129, 120, 111, 102, 93, 79, 88, 97, 105, 114, 123, 132, 141, 150, 135, 126, 118, 109, 100, 91, 82, 73, 65, 56, 33, 42, 50, 59, 68, 77, 86, 95, 103, 112, 98, 89, 80, 71, 63, 54, 45, 36, 27, 18, 252, 4, 13, 22, 31, 39, 48, 57, 66, 75, 52, 43, 34, 25, 16, 8, 255, 246, 237, 214, 223, 232, 241, 250, 2, 11, 20, 29, 37, 14, 5, 253, 244, 235, 226, 218, 209, 200, 191 }; + static const auto (&radiusProxy)[NUM_PIXELS] = physicalToFibonacci; + static const uint8_t RADII_SCALE_DIVISOR { 1 }; + static const uint8_t RADII_SCALE_MULTIPLIER { 2 }; #elif defined(PRODUCT_FIBONACCI64_FULL) || defined(PRODUCT_FIBONACCI64_MINI) const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 39, 52, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 51, 38, 25, 12, 4, 17, 30, 43, 56, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60 }; const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 39, 19, 58, 29, 9, 48, 20, 59, 38, 10, 49, 28, 1, 40, 18, 57, 30, 8, 47, 21, 60, 37, 11, 50, 27, 2, 41, 17, 56, 31, 7, 46, 22, 61, 36, 12, 51, 26, 3, 42, 16, 55, 32, 6, 45, 23, 62, 35, 13, 52, 25, 4, 43, 15, 54, 33, 5, 44, 24, 63, 34, 14, 53 }; const uint8_t coordsX[NUM_PIXELS] { 140, 189, 208, 214, 208, 146, 168, 180, 180, 162, 152, 146, 129, 103, 72, 40, 70, 97, 120, 131, 107, 79, 50, 23, 0, 7, 23, 46, 76, 93, 57, 37, 28, 29, 87, 68, 59, 62, 80, 113, 91, 94, 109, 133, 202, 172, 145, 125, 117, 145, 170, 198, 227, 253, 255, 235, 210, 181, 148, 175, 207, 228, 240, 244 }; const uint8_t coordsY[NUM_PIXELS] { 128, 114, 91, 63, 34, 0, 21, 48, 76, 106, 78, 47, 25, 11, 5, 38, 35, 42, 61, 101, 87, 69, 68, 78, 98, 143, 118, 102, 98, 122, 131, 152, 179, 209, 255, 230, 202, 174, 148, 142, 181, 210, 235, 252, 235, 234, 224, 203, 170, 183, 201, 205, 198, 181, 134, 157, 171, 173, 153, 145, 138, 120, 93, 63 }; const uint8_t angles[NUM_PIXELS] { 0, 249, 241, 232, 223, 200, 208, 217, 226, 235, 212, 203, 194, 185, 176, 162, 171, 180, 188, 197, 174, 165, 156, 147, 139, 124, 133, 142, 151, 136, 128, 119, 110, 101, 78, 86, 95, 104, 113, 99, 90, 81, 72, 63, 40, 49, 58, 67, 75, 52, 43, 34, 25, 17, 2, 11, 20, 29, 38, 14, 6, 255, 246, 237 }; + static const auto (&radiusProxy)[NUM_PIXELS] = physicalToFibonacci; + static const uint8_t RADII_SCALE_DIVISOR { 1 }; + static const uint8_t RADII_SCALE_MULTIPLIER { 4 }; #elif defined(PRODUCT_FIBONACCI32) const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 31, 18, 5, 10, 23, 28, 15, 2, 7, 20, 33, 25, 12, 4, 17, 30, 22, 9, 1, 14, 27, 32, 19, 6, 11, 24, 29, 16, 3, 8, 21 }; const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 21, 10, 31, 16, 5, 26, 11, 32, 20, 6, 27, 15, 1, 22, 9, 30, 17, 4, 25, 12, 33, 19, 7, 28, 14, 2, 23, 8, 29, 18, 3, 24, 13 }; @@ -87,6 +99,9 @@ const uint8_t angles[NUM_PIXELS] { 0, 249, 241, 232, 223, 200, 208, 217, 226, 235, 212, 203, 194, 185, 176, 162, 171, 180, 188, 197, 174, 165, 156, 147, 139, 124, 133, 142, 151, 136, 128, 119, 110, 101, 78, 86, 95, 104, 113, 99, 90, 81, 72, 63, 40, 49, 58, 67, 75, 52, 43, 34, 25, 17, 2, 11, 20, 29, 38, 14, 6, 255, 246, 237 }; const uint8_t body[NUM_PIXELS] { 0, 16, 32, 48, 64, 80, 96, 112, 128, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 255 }; static_assert(NUM_PIXELS == ARRAY_SIZE2(body), ""); + static const auto (&radiusProxy)[NUM_PIXELS] = body; + static const uint8_t RADII_SCALE_DIVISOR { 1 }; // body[] values are already in range [0..255] + static const uint8_t RADII_SCALE_MULTIPLIER { 1 }; // body[] values are already in range [0..255] // For reference purposes... // const uint8_t head[9] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; // const uint8_t tentacle0[8] { 9, 10, 11, 12, 13, 14, 15, 16 }; @@ -96,53 +111,87 @@ // const uint8_t tentacle4[8] { 40, 41, 42, 43, 44, 45, 46, 47 }; // const uint8_t tentacle5[8] { 48, 49, 50, 51, 52, 53, 54, 55 }; // const uint8_t tentacle6[8] { 56, 57, 58, 59, 60, 61, 62, 63 }; +#elif defined(PRODUCT_1628_RINGS) + // Yes, this is 1628 pixels ... all driven by one ESP8266 + // 20 concentric rings of pixel goodness! + const uint8_t coordsX[NUM_PIXELS] { 134, 128, 121, 128, 140, 139, 134, 128, 121, 116, 115, 116, 121, 128, 134, 139, 147, 146, 143, 139, 134, 129, 123, 118, 113, 110, 109, 109, 110, 113, 118, 123, 129, 134, 139, 143, 146, 153, 152, 151, 148, 144, 139, 134, 129, 123, 118, 113, 109, 106, 103, 102, 102, 103, 106, 109, 113, 118, 123, 129, 134, 139, 144, 148, 151, 152, 159, 159, 158, 155, 152, 149, 144, 139, 134, 129, 123, 118, 113, 109, 104, 101, 98, 97, 96, 96, 97, 98, 101, 104, 109, 113, 118, 123, 129, 134, 139, 144, 149, 152, 155, 158, 159, 166, 165, 164, 162, 160, 157, 153, 149, 144, 139, 134, 129, 124, 118, 113, 108, 104, 100, 97, 94, 92, 90, 89, 89, 90, 92, 94, 97, 100, 104, 108, 113, 118, 124, 129, 134, 139, 144, 149, 153, 157, 160, 162, 164, 165, 172, 172, 171, 169, 167, 165, 161, 158, 154, 149, 144, 139, 134, 129, 124, 118, 113, 108, 104, 99, 95, 92, 89, 87, 85, 84, 83, 83, 84, 85, 87, 89, 92, 95, 99, 104, 108, 113, 118, 124, 129, 134, 139, 144, 149, 154, 158, 161, 165, 167, 169, 171, 172, 179, 178, 177, 176, 174, 172, 169, 166, 163, 159, 154, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 101, 96, 92, 89, 86, 83, 81, 79, 78, 77, 77, 77, 78, 79, 81, 83, 86, 89, 92, 96, 101, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 154, 159, 163, 166, 169, 172, 174, 176, 177, 178, 185, 185, 184, 183, 181, 179, 177, 174, 171, 167, 163, 159, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 96, 92, 88, 84, 81, 78, 76, 74, 72, 71, 70, 70, 70, 71, 72, 74, 76, 78, 81, 84, 88, 92, 96, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 159, 163, 167, 171, 174, 177, 179, 181, 183, 184, 185, 191, 191, 190, 189, 188, 186, 184, 181, 178, 175, 172, 168, 164, 159, 155, 150, 145, 140, + 135, 130, 125, 120, 115, 110, 105, 100, 96, 91, 87, 83, 80, 77, 74, 71, 69, 67, 66, 65, 64, 64, 64, 65, 66, 67, 69, 71, 74, 77, 80, 83, 87, 91, 96, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 159, 164, 168, 172, 175, 178, 181, 184, 186, 188, 189, 190, 191, 198, 197, 197, 196, 195, 193, 191, 189, 186, 183, 180, 176, 172, 168, 164, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 91, 87, 83, 79, 75, 72, 69, 66, 64, 62, 60, 59, 58, 58, 57, 58, 58, 59, 60, 62, 64, 66, 69, 72, 75, 79, 83, 87, 91, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 164, 168, 172, 176, 180, 183, 186, 189, 191, 193, 195, 196, 197, 197, 204, 204, 203, 202, 201, 200, 198, 196, 193, 191, 188, 184, 181, 177, 173, 169, 164, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 91, 86, 82, 78, 74, 71, 67, 64, 62, 59, 57, 55, 54, 53, 52, 51, 51, 51, 52, 53, 54, 55, 57, 59, 62, 64, 67, 71, 74, 78, 82, 86, 91, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 164, 169, 173, 177, 181, 184, 188, 191, 193, 196, 198, 200, 201, 202, 203, 204, 210, 210, 210, 209, 208, 206, 205, 203, 201, 198, 195, 192, 189, 185, 181, 177, 173, 169, 164, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 91, 86, 82, 78, 74, 70, 66, 63, 60, 57, 54, 52, 50, 49, 47, 46, 45, 45, 45, 45, 45, 46, 47, 49, 50, 52, 54, 57, 60, 63, 66, 70, 74, 78, 82, 86, 91, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 164, 169, 173, 177, 181, 185, 189, 192, 195, 198, 201, 203, 205, 206, 208, 209, 210, 210, 217, 217, 216, 215, 214, 213, 212, 210, 208, 205, 203, 200, 197, 193, 190, 186, 182, 178, 174, + 169, 165, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 90, 86, 81, 77, 73, 69, 65, 62, 58, 55, 52, 50, 47, 45, 43, 42, 41, 40, 39, 38, 38, 38, 39, 40, 41, 42, 43, 45, 47, 50, 52, 55, 58, 62, 65, 69, 73, 77, 81, 86, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 169, 174, 178, 182, 186, 190, 193, 197, 200, 203, 205, 208, 210, 212, 213, 214, 215, 216, 217, 223, 223, 223, 222, 221, 220, 218, 217, 215, 212, 210, 207, 204, 201, 198, 194, 190, 187, 182, 178, 174, 169, 165, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 90, 86, 81, 77, 73, 68, 65, 61, 57, 54, 51, 48, 45, 43, 40, 38, 37, 35, 34, 33, 32, 32, 32, 32, 32, 33, 34, 35, 37, 38, 40, 43, 45, 48, 51, 54, 57, 61, 65, 68, 73, 77, 81, 86, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 169, 174, 178, 182, 187, 190, 194, 198, 201, 204, 207, 210, 212, 215, 217, 218, 220, 221, 222, 223, 223, 230, 229, 229, 228, 227, 226, 225, 223, 221, 219, 217, 214, 212, 208, 205, 202, 198, 194, 191, 186, 182, 178, 173, 169, 164, 159, 154, 149, 144, 139, 134, 129, 124, 119, 113, 108, 103, 98, 94, 89, 84, 79, 75, 71, 67, 62, 59, 55, 51, 48, 45, 42, 39, 37, 35, 33, 31, 29, 28, 27, 26, 26, 26, 26, 26, 26, 27, 28, 29, 31, 33, 35, 37, 39, 42, 45, 48, 51, 55, 59, 62, 67, 71, 75, 79, 84, 89, 94, 98, 103, 108, 113, 119, 124, 129, 134, 139, 144, 149, 154, 159, 164, 169, 173, 178, 182, 186, 191, 194, 198, 202, 205, 208, 212, 214, 217, 219, 221, 223, 225, 226, 227, 228, 229, 229, 236, 236, 235, 235, 234, 233, 232, 230, 228, 227, 224, 222, 219, 217, 214, 211, 207, 204, 200, 196, 192, 188, 184, 179, 175, 170, 166, 161, 156, 151, + 146, 141, 136, 131, 126, 121, 116, 111, 106, 101, 96, 92, 87, 82, 78, 73, 69, 65, 61, 57, 53, 50, 46, 43, 40, 37, 34, 32, 30, 27, 26, 24, 23, 21, 21, 20, 19, 19, 19, 19, 20, 21, 21, 23, 24, 26, 27, 30, 32, 34, 37, 40, 43, 46, 50, 53, 57, 61, 65, 69, 73, 78, 82, 87, 92, 96, 101, 106, 111, 116, 121, 126, 131, 136, 141, 146, 151, 156, 161, 166, 170, 175, 179, 184, 188, 192, 196, 200, 204, 207, 211, 214, 217, 219, 222, 224, 227, 228, 230, 232, 233, 234, 235, 235, 236, 242, 242, 242, 241, 240, 239, 238, 237, 235, 233, 231, 229, 226, 224, 221, 218, 215, 211, 208, 204, 200, 196, 192, 188, 183, 179, 174, 170, 165, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 90, 85, 81, 76, 72, 67, 63, 59, 55, 51, 47, 44, 40, 37, 34, 31, 29, 26, 24, 22, 20, 18, 17, 16, 15, 14, 13, 13, 13, 13, 13, 14, 15, 16, 17, 18, 20, 22, 24, 26, 29, 31, 34, 37, 40, 44, 47, 51, 55, 59, 63, 67, 72, 76, 81, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 174, 179, 183, 188, 192, 196, 200, 204, 208, 211, 215, 218, 221, 224, 226, 229, 231, 233, 235, 237, 238, 239, 240, 241, 242, 242, 249, 249, 248, 248, 247, 246, 245, 243, 241, 240, 237, 235, 233, 230, 227, 224, 221, 217, 214, 210, 206, 202, 198, 193, 189, 184, 180, 175, 170, 165, 160, 155, 150, 145, 139, 134, 129, 124, 118, 113, 108, 103, 98, 93, 88, 83, 78, 73, 68, 64, 60, 55, 51, 47, 43, 40, 36, 33, 30, 27, 24, 21, 19, 16, 14, 13, 11, 10, 9, 8, 7, 7, 6, 6, 7, 7, 8, 9, 10, 11, 13, 14, 16, 19, 21, 24, 27, 30, 33, 36, 40, 43, 47, 51, 55, 60, 64, 68, 73, 78, 83, 88, 93, 98, 103, 108, 113, 118, 124, 129, 134, 139, 145, 150, 155, 160, 165, 170, 175, 180, 184, 189, 193, 198, 202, 206, + 210, 214, 217, 221, 224, 227, 230, 233, 235, 237, 240, 241, 243, 245, 246, 247, 248, 248, 249, 255, 255, 255, 254, 253, 253, 251, 250, 249, 247, 245, 243, 241, 239, 236, 234, 231, 228, 224, 221, 218, 214, 210, 206, 202, 198, 194, 190, 185, 181, 176, 172, 167, 162, 157, 152, 147, 142, 138, 133, 128, 122, 117, 113, 108, 103, 98, 93, 88, 83, 79, 74, 70, 65, 61, 57, 53, 49, 45, 41, 37, 34, 31, 27, 24, 21, 19, 16, 14, 12, 10, 8, 6, 5, 4, 2, 2, 1, 0, 0, 0, 0, 0, 1, 2, 2, 4, 5, 6, 8, 10, 12, 14, 16, 19, 21, 24, 27, 31, 34, 37, 41, 45, 49, 53, 57, 61, 65, 70, 74, 79, 83, 88, 93, 98, 103, 108, 113, 117, 122, 127, 133, 138, 142, 147, 152, 157, 162, 167, 172, 176, 181, 185, 190, 194, 198, 202, 206, 210, 214, 218, 221, 224, 228, 231, 234, 236, 239, 241, 243, 245, 247, 249, 250, 251, 253, 253, 254, 255, 255 }; + const uint8_t coordsY[NUM_PIXELS] { 128, 134, 128, 121, 128, 134, 139, 140, 139, 134, 128, 121, 116, 115, 116, 121, 128, 133, 138, 142, 145, 147, 146, 144, 141, 136, 130, 125, 119, 114, 111, 109, 108, 110, 113, 117, 122, 128, 133, 138, 143, 147, 150, 152, 153, 153, 151, 149, 145, 141, 136, 130, 125, 119, 114, 110, 106, 104, 102, 102, 103, 105, 108, 112, 117, 122, 128, 133, 138, 143, 148, 151, 155, 157, 159, 159, 159, 158, 156, 153, 150, 145, 141, 136, 130, 125, 119, 114, 110, 105, 102, 99, 97, 96, 96, 96, 98, 100, 104, 107, 112, 117, 122, 128, 133, 138, 143, 148, 152, 156, 159, 162, 164, 165, 166, 166, 165, 163, 161, 158, 154, 150, 145, 141, 135, 130, 125, 120, 114, 110, 105, 101, 97, 94, 92, 90, 89, 89, 90, 91, 93, 96, 99, 103, 107, 112, 117, 122, 128, 133, 138, 143, 148, 152, 157, 160, 164, 167, 169, 171, 172, 172, 172, 171, 170, 168, 165, 162, 159, 155, 150, 145, 141, 135, 130, 125, 120, 114, 110, 105, 100, 96, 93, 90, 87, 85, 84, 83, 83, 83, 84, 86, 88, 91, 95, 98, 103, 107, 112, 117, 122, 128, 133, 138, 143, 148, 152, 157, 161, 164, 168, 171, 173, 175, 177, 178, 178, 178, 178, 177, 175, 173, 171, 168, 164, 161, 157, 152, 148, 143, 138, 133, 128, 122, 117, 112, 107, 103, 98, 94, 91, 87, 84, 82, 80, 78, 77, 77, 77, 77, 78, 80, 82, 84, 87, 91, 94, 98, 103, 107, 112, 117, 122, 128, 133, 138, 143, 148, 152, 157, 161, 165, 169, 172, 175, 178, 180, 182, 183, 184, 185, 185, 184, 183, 182, 180, 178, 175, 172, 169, 165, 161, 157, 152, 148, 143, 138, 133, 128, 122, 117, 112, 107, 103, 98, 94, 90, 86, 83, 80, 77, 75, 73, 72, 71, 70, 70, 71, 72, 73, 75, 77, 80, 83, 86, 90, 94, 98, 103, 107, 112, 117, 122, 128, 133, 138, 143, 148, 152, 157, 162, 166, 170, 173, 177, 180, 183, 185, 187, 189, 190, + 191, 191, 191, 191, 190, 189, 187, 185, 183, 180, 177, 173, 170, 166, 162, 157, 152, 148, 143, 138, 133, 128, 122, 117, 112, 107, 103, 98, 93, 89, 85, 82, 78, 75, 72, 70, 68, 66, 65, 64, 64, 64, 64, 65, 66, 68, 70, 72, 75, 78, 82, 85, 89, 93, 98, 103, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 157, 162, 166, 170, 174, 178, 181, 185, 187, 190, 192, 194, 195, 196, 197, 198, 198, 197, 196, 195, 194, 192, 190, 187, 185, 181, 178, 174, 170, 166, 162, 157, 153, 148, 143, 138, 133, 128, 122, 117, 112, 107, 102, 98, 93, 89, 85, 81, 77, 74, 70, 68, 65, 63, 61, 60, 59, 58, 57, 57, 58, 59, 60, 61, 63, 65, 68, 70, 74, 77, 81, 85, 89, 93, 98, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 157, 162, 166, 171, 175, 179, 182, 186, 189, 192, 195, 197, 199, 201, 202, 203, 204, 204, 204, 204, 203, 202, 201, 199, 197, 195, 192, 189, 186, 182, 179, 175, 171, 166, 162, 157, 153, 148, 143, 138, 133, 128, 122, 117, 112, 107, 102, 98, 93, 89, 84, 80, 76, 73, 69, 66, 63, 60, 58, 56, 54, 53, 52, 51, 51, 51, 51, 52, 53, 54, 56, 58, 60, 63, 66, 69, 73, 76, 80, 84, 89, 93, 98, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 157, 162, 167, 171, 175, 179, 183, 187, 190, 194, 197, 199, 202, 204, 206, 207, 208, 209, 210, 210, 210, 210, 209, 208, 207, 206, 204, 202, 199, 197, 194, 190, 187, 183, 179, 175, 171, 167, 162, 157, 153, 148, 143, 138, 133, 128, 122, 117, 112, 107, 102, 98, 93, 88, 84, 80, 76, 72, 68, 65, 61, 58, 56, 53, 51, 49, 48, 47, 46, 45, 45, 45, 45, 46, 47, 48, 49, 51, 53, 56, 58, 61, 65, 68, 72, 76, 80, 84, 88, 93, 98, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 157, 162, 167, 171, 176, 180, 184, 188, 192, 195, 198, 201, 204, 206, 209, + 211, 212, 214, 215, 216, 216, 217, 217, 216, 216, 215, 214, 212, 211, 209, 206, 204, 201, 198, 195, 192, 188, 184, 180, 176, 171, 167, 162, 157, 153, 148, 143, 138, 133, 128, 122, 117, 112, 107, 102, 98, 93, 88, 84, 79, 75, 71, 67, 63, 60, 57, 54, 51, 49, 46, 44, 43, 41, 40, 39, 39, 38, 38, 39, 39, 40, 41, 43, 44, 46, 49, 51, 54, 57, 60, 63, 67, 71, 75, 79, 84, 88, 93, 98, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 158, 162, 167, 172, 176, 180, 185, 189, 192, 196, 199, 203, 206, 209, 211, 213, 216, 217, 219, 220, 221, 222, 223, 223, 223, 223, 222, 221, 220, 219, 217, 216, 213, 211, 209, 206, 203, 199, 196, 192, 189, 185, 180, 176, 172, 167, 162, 158, 153, 148, 143, 138, 133, 128, 122, 117, 112, 107, 102, 97, 93, 88, 83, 79, 75, 70, 66, 63, 59, 56, 52, 49, 46, 44, 42, 39, 38, 36, 35, 34, 33, 32, 32, 32, 32, 33, 34, 35, 36, 38, 39, 42, 44, 46, 49, 52, 56, 59, 63, 66, 70, 75, 79, 83, 88, 93, 97, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 158, 163, 167, 172, 177, 181, 185, 190, 193, 197, 201, 204, 208, 211, 214, 216, 219, 221, 223, 225, 226, 227, 228, 229, 229, 229, 229, 229, 229, 228, 227, 225, 224, 222, 220, 217, 215, 212, 209, 206, 203, 199, 195, 192, 187, 183, 179, 174, 170, 165, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 90, 85, 81, 76, 72, 68, 63, 60, 56, 52, 49, 46, 43, 40, 38, 35, 33, 31, 30, 28, 27, 26, 26, 26, 26, 26, 26, 27, 28, 29, 30, 32, 34, 36, 39, 41, 44, 47, 51, 54, 58, 62, 65, 70, 74, 78, 83, 88, 92, 97, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 152, 157, 162, 167, 172, 176, 181, 185, 189, 193, 197, 201, 205, 208, 211, 214, 217, 220, 223, 225, 227, 229, 231, 232, 233, 234, 235, 236, + 236, 236, 236, 235, 235, 234, 233, 231, 230, 228, 226, 224, 221, 219, 216, 213, 210, 206, 203, 199, 195, 191, 187, 183, 178, 174, 169, 165, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 90, 86, 81, 77, 72, 68, 64, 60, 56, 52, 49, 45, 42, 39, 36, 34, 31, 29, 27, 25, 24, 22, 21, 20, 20, 19, 19, 19, 19, 20, 21, 22, 23, 24, 26, 28, 30, 32, 35, 38, 41, 44, 47, 50, 54, 58, 62, 66, 70, 74, 79, 83, 88, 93, 98, 103, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 158, 162, 167, 172, 177, 181, 186, 190, 194, 198, 202, 206, 210, 213, 216, 219, 222, 225, 228, 230, 232, 234, 236, 238, 239, 240, 241, 242, 242, 242, 242, 242, 242, 241, 240, 239, 238, 236, 234, 232, 230, 228, 225, 222, 219, 216, 213, 210, 206, 202, 198, 194, 190, 186, 181, 177, 172, 167, 162, 158, 153, 148, 143, 138, 133, 128, 122, 117, 112, 107, 102, 97, 93, 88, 83, 78, 74, 69, 65, 61, 57, 53, 49, 45, 42, 39, 36, 33, 30, 27, 25, 23, 21, 19, 17, 16, 15, 14, 13, 13, 13, 13, 13, 13, 14, 15, 16, 17, 19, 21, 23, 25, 27, 30, 33, 36, 39, 42, 45, 49, 53, 57, 61, 65, 69, 74, 78, 83, 88, 93, 97, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 154, 159, 164, 169, 174, 178, 183, 188, 192, 197, 201, 205, 209, 213, 216, 220, 223, 226, 229, 232, 235, 237, 239, 241, 243, 244, 246, 247, 247, 248, 248, 249, 249, 248, 248, 247, 246, 245, 243, 242, 240, 238, 236, 233, 231, 228, 225, 221, 218, 215, 211, 207, 203, 199, 194, 190, 185, 181, 176, 171, 166, 161, 156, 151, 146, 141, 135, 130, 125, 120, 114, 109, 104, 99, 94, 89, 84, 79, 74, 70, 65, 61, 56, 52, 48, 44, 40, 37, 34, 30, 27, 24, 22, 19, 17, 15, 13, 12, 10, 9, 8, 7, 7, 6, 6, 7, 7, 8, 8, 9, 11, 12, 14, 16, 18, 20, 23, 26, 29, 32, 35, + 39, 42, 46, 50, 54, 58, 63, 67, 72, 77, 81, 86, 91, 96, 101, 107, 112, 117, 122, 128, 133, 138, 142, 147, 152, 157, 162, 167, 172, 176, 181, 185, 190, 194, 198, 202, 206, 210, 214, 218, 221, 224, 228, 231, 234, 236, 239, 241, 243, 245, 247, 249, 250, 251, 253, 253, 254, 255, 255, 255, 255, 255, 254, 253, 253, 251, 250, 249, 247, 245, 243, 241, 239, 236, 234, 231, 228, 224, 221, 218, 214, 210, 206, 202, 198, 194, 190, 185, 181, 176, 172, 167, 162, 157, 152, 147, 142, 138, 133, 128, 122, 117, 113, 108, 103, 98, 93, 88, 83, 79, 74, 70, 65, 61, 57, 53, 49, 45, 41, 37, 34, 31, 27, 24, 21, 19, 16, 14, 12, 10, 8, 6, 5, 4, 2, 2, 1, 0, 0, 0, 0, 0, 1, 2, 2, 4, 5, 6, 8, 10, 12, 14, 16, 19, 21, 24, 27, 31, 34, 37, 41, 45, 49, 53, 57, 61, 65, 70, 74, 79, 83, 88, 93, 98, 103, 108, 113, 117, 122 }; + const uint8_t angles[NUM_PIXELS] { 0, 64, 128, 191, 0, 21, 43, 64, 85, 106, 128, 149, 170, 191, 213, 234, 0, 12, 24, 36, 49, 61, 73, 85, 97, 109, 121, 134, 146, 158, 170, 182, 194, 206, 219, 231, 243, 0, 9, 18, 26, 35, 44, 53, 62, 70, 79, 88, 97, 106, 114, 123, 132, 141, 149, 158, 167, 176, 185, 193, 202, 211, 220, 229, 237, 246, 0, 7, 14, 21, 28, 34, 41, 48, 55, 62, 69, 76, 83, 90, 96, 103, 110, 117, 124, 131, 138, 145, 152, 159, 165, 172, 179, 186, 193, 200, 207, 214, 221, 227, 234, 241, 248, 0, 6, 11, 17, 23, 28, 34, 40, 45, 51, 57, 62, 68, 74, 79, 85, 91, 96, 102, 108, 113, 119, 125, 130, 136, 142, 147, 153, 159, 164, 170, 176, 181, 187, 193, 198, 204, 210, 215, 221, 227, 232, 238, 244, 249, 0, 5, 10, 14, 19, 24, 29, 34, 38, 43, 48, 53, 58, 63, 67, 72, 77, 82, 87, 91, 96, 101, 106, 111, 115, 120, 125, 130, 135, 140, 144, 149, 154, 159, 164, 168, 173, 178, 183, 188, 192, 197, 202, 207, 212, 217, 221, 226, 231, 236, 241, 245, 250, 0, 4, 8, 12, 16, 21, 25, 29, 33, 37, 41, 45, 49, 53, 58, 62, 66, 70, 74, 78, 82, 86, 90, 95, 99, 103, 107, 111, 115, 119, 123, 128, 132, 136, 140, 144, 148, 152, 156, 160, 165, 169, 173, 177, 181, 185, 189, 193, 197, 202, 206, 210, 214, 218, 222, 226, 230, 234, 239, 243, 247, 251, 0, 4, 7, 11, 15, 18, 22, 26, 29, 33, 36, 40, 44, 47, 51, 55, 58, 62, 66, 69, 73, 77, 80, 84, 87, 91, 95, 98, 102, 106, 109, 113, 117, 120, 124, 128, 131, 135, 138, 142, 146, 149, 153, 157, 160, 164, 168, 171, 175, 179, 182, 186, 189, 193, 197, 200, 204, 208, 211, 215, 219, 222, 226, 230, 233, 237, 240, 244, 248, 251, 0, 3, 7, 10, 13, 16, 20, 23, 26, 29, 33, 36, 39, 43, 46, 49, 52, 56, 59, 62, 65, 69, 72, 75, 78, 82, 85, 88, 92, 95, 98, 101, 105, 108, 111, 114, 118, 121, 124, 127, + 131, 134, 137, 141, 144, 147, 150, 154, 157, 160, 163, 167, 170, 173, 177, 180, 183, 186, 190, 193, 196, 199, 203, 206, 209, 213, 216, 219, 222, 226, 229, 232, 235, 239, 242, 245, 248, 252, 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98, 101, 104, 107, 110, 113, 116, 119, 122, 125, 128, 130, 133, 136, 139, 142, 145, 148, 151, 154, 157, 160, 163, 166, 169, 172, 175, 178, 181, 184, 187, 190, 193, 196, 199, 202, 205, 208, 211, 213, 216, 219, 222, 225, 228, 231, 234, 237, 240, 243, 246, 249, 252, 0, 3, 5, 8, 11, 14, 16, 19, 22, 24, 27, 30, 33, 35, 38, 41, 43, 46, 49, 52, 54, 57, 60, 62, 65, 68, 71, 73, 76, 79, 81, 84, 87, 90, 92, 95, 98, 100, 103, 106, 109, 111, 114, 117, 119, 122, 125, 128, 130, 133, 136, 138, 141, 144, 146, 149, 152, 155, 157, 160, 163, 165, 168, 171, 174, 176, 179, 182, 184, 187, 190, 193, 195, 198, 201, 203, 206, 209, 212, 214, 217, 220, 222, 225, 228, 231, 233, 236, 239, 241, 244, 247, 250, 252, 0, 3, 5, 8, 10, 13, 15, 17, 20, 23, 25, 27, 30, 33, 35, 37, 40, 43, 45, 48, 50, 53, 55, 57, 60, 63, 65, 68, 70, 73, 75, 78, 80, 83, 85, 88, 90, 93, 95, 98, 100, 102, 105, 107, 110, 113, 115, 118, 120, 123, 125, 128, 130, 133, 135, 138, 140, 142, 145, 147, 150, 153, 155, 158, 160, 163, 165, 168, 170, 173, 175, 178, 180, 182, 185, 187, 190, 193, 195, 198, 200, 203, 205, 208, 210, 213, 215, 218, 220, 223, 225, 228, 230, 233, 235, 238, 240, 243, 245, 247, 250, 252, 0, 2, 5, 7, 9, 12, 14, 16, 19, 21, 23, 26, 28, 30, 32, 35, 37, 39, 42, 44, 46, 49, 51, 53, 56, 58, 60, 63, 65, 67, 70, 72, 74, 77, 79, 81, 83, 86, 88, 90, 93, 95, 97, 100, 102, 104, 107, 109, 111, 114, + 116, 118, 121, 123, 125, 128, 130, 132, 134, 137, 139, 141, 144, 146, 148, 151, 153, 155, 158, 160, 162, 165, 167, 169, 172, 174, 176, 179, 181, 183, 185, 188, 190, 192, 195, 197, 199, 202, 204, 206, 209, 211, 213, 216, 218, 220, 223, 225, 227, 230, 232, 234, 236, 239, 241, 243, 246, 248, 250, 253, 0, 2, 4, 6, 9, 11, 13, 15, 17, 19, 22, 24, 26, 28, 30, 32, 35, 37, 39, 41, 43, 45, 48, 50, 52, 54, 56, 58, 61, 63, 65, 67, 69, 71, 73, 76, 78, 80, 82, 84, 86, 89, 91, 93, 95, 97, 99, 102, 104, 106, 108, 110, 112, 115, 117, 119, 121, 123, 125, 128, 130, 132, 134, 136, 138, 140, 143, 145, 147, 149, 151, 153, 156, 158, 160, 162, 164, 166, 169, 171, 173, 175, 177, 179, 182, 184, 186, 188, 190, 192, 194, 197, 199, 201, 203, 205, 207, 210, 212, 214, 216, 218, 220, 223, 225, 227, 229, 231, 233, 236, 238, 240, 242, 244, 246, 249, 251, 253, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 0, 2, 4, 6, 8, 9, 11, 13, 15, 17, 19, 21, 23, 25, 26, 28, 30, 32, 34, 36, 38, 40, 42, 43, 45, 47, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66, 68, 70, 72, 74, 76, 77, 79, 81, 83, 85, 87, 89, 91, 93, 94, 96, 98, 100, 102, 104, 106, 108, 110, 111, 113, 115, 117, 119, 121, 123, + 125, 127, 128, 130, 132, 134, 136, 138, 140, 142, 144, 145, 147, 149, 151, 153, 155, 157, 159, 161, 162, 164, 166, 168, 170, 172, 174, 176, 178, 179, 181, 183, 185, 187, 189, 191, 193, 195, 196, 198, 200, 202, 204, 206, 208, 210, 212, 213, 215, 217, 219, 221, 223, 225, 227, 229, 230, 232, 234, 236, 238, 240, 242, 244, 246, 247, 249, 251, 253, 0, 2, 4, 5, 7, 9, 11, 13, 14, 16, 18, 20, 22, 23, 25, 27, 29, 31, 32, 34, 36, 38, 40, 41, 43, 45, 47, 48, 50, 52, 54, 56, 57, 59, 61, 63, 65, 66, 68, 70, 72, 74, 75, 77, 79, 81, 83, 84, 86, 88, 90, 92, 93, 95, 97, 99, 101, 102, 104, 106, 108, 110, 111, 113, 115, 117, 119, 120, 122, 124, 126, 128, 129, 131, 133, 135, 136, 138, 140, 142, 144, 145, 147, 149, 151, 153, 154, 156, 158, 160, 162, 163, 165, 167, 169, 171, 172, 174, 176, 178, 180, 181, 183, 185, 187, 189, 190, 192, 194, 196, 198, 199, 201, 203, 205, 207, 208, 210, 212, 214, 215, 217, 219, 221, 223, 224, 226, 228, 230, 232, 233, 235, 237, 239, 241, 242, 244, 246, 248, 250, 251, 253, 0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 18, 19, 21, 23, 25, 26, 28, 30, 32, 33, 35, 37, 39, 40, 42, 44, 46, 47, 49, 51, 53, 55, 56, 58, 60, 62, 63, 65, 67, 69, 70, 72, 74, 76, 77, 79, 81, 83, 84, 86, 88, 90, 91, 93, 95, 97, 98, 100, 102, 104, 106, 107, 109, 111, 113, 114, 116, 118, 120, 121, 123, 125, 127, 128, 130, 132, 134, 135, 137, 139, 141, 142, 144, 146, 148, 149, 151, 153, 155, 157, 158, 160, 162, 164, 165, 167, 169, 171, 172, 174, 176, 178, 179, 181, 183, 185, 186, 188, 190, 192, 193, 195, 197, 199, 200, 202, 204, 206, 208, 209, 211, 213, 215, 216, 218, 220, 222, 223, 225, 227, 229, 230, 232, 234, 236, 237, 239, 241, 243, 244, 246, 248, 250, 251, 253, 0, 2, 3, 5, 6, 8, 10, + 11, 13, 14, 16, 18, 19, 21, 22, 24, 26, 27, 29, 30, 32, 33, 35, 37, 38, 40, 41, 43, 45, 46, 48, 49, 51, 53, 54, 56, 57, 59, 61, 62, 64, 65, 67, 69, 70, 72, 73, 75, 77, 78, 80, 81, 83, 84, 86, 88, 89, 91, 92, 94, 96, 97, 99, 100, 102, 104, 105, 107, 108, 110, 112, 113, 115, 116, 118, 120, 121, 123, 124, 126, 128, 129, 131, 132, 134, 135, 137, 139, 140, 142, 143, 145, 147, 148, 150, 151, 153, 155, 156, 158, 159, 161, 163, 164, 166, 167, 169, 171, 172, 174, 175, 177, 179, 180, 182, 183, 185, 186, 188, 190, 191, 193, 194, 196, 198, 199, 201, 202, 204, 206, 207, 209, 210, 212, 214, 215, 217, 218, 220, 222, 223, 225, 226, 228, 230, 231, 233, 234, 236, 237, 239, 241, 242, 244, 245, 247, 249, 250, 252, 253 }; + const uint8_t radii[NUM_PIXELS] { 13, 13, 13, 13, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, + 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 217, 217, + 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }; + static const auto (&radiusProxy)[NUM_PIXELS] = radii; + static const uint8_t RADII_SCALE_DIVISOR { 1 }; // radii[] values are already in range [0..255] + static const uint8_t RADII_SCALE_MULTIPLIER { 1 }; // radii[] values are already in range [0..255] + + // Polar coordinate mapping code for FastLED by Adam Haile, Maniacal Labs: + // http://maniacallabs.com/2015/05/04/review-code-adafruit-dotstar-disk/ + // https://gist.github.com/adammhaile/a769f3ff87ff61f22ace + + #define ringCount 20 // Total Number of Rings. AdaFruit Disk has 10 + #define lastRing (ringCount-1) // for convenience + + //Map rings on disk to indicies. + //Each represents one of the concentric rings. + //TODO: change to structure with min/max (inclusive), to clarify meaning of indices + const uint16_t rings[ringCount][2] { + // { first pixel of the ring, last pixel of the ring } // INCLUSIVE indices + { 0, 3 }, + { 4, 15 }, + { 16, 36 }, + { 37, 65 }, + { 66, 102 }, + { 103, 147 }, + { 148, 200 }, + { 201, 262 }, + { 263, 332 }, + { 333, 410 }, + { 411, 496 }, + { 497, 590 }, + { 591, 692 }, + { 693, 803 }, + { 804, 920 }, + { 921, 1045 }, + { 1046, 1180 }, + { 1181, 1322 }, + { 1323, 1467 }, + { 1468, 1627 }, + }; + + #else - #error "Unknown / Unsupported fibonacci product ... no mappings defined" + #error "Unknown / Unsupported product ... no mappings defined" #endif #if IS_FIBONACCI static_assert(NUM_PIXELS == ARRAY_SIZE2(physicalToFibonacci), ""); static_assert(NUM_PIXELS == ARRAY_SIZE2(fibonacciToPhysical), ""); #endif -#if HAS_COORDINATE_MAP - static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsX), ""); - static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsY), ""); - static_assert(NUM_PIXELS == ARRAY_SIZE2(angles), ""); -#endif // What is HAS_RADIUS_PROXY? It could be the actual radius, or it could be something // that is used "in place of" the radius during effects processing. // Use reference to original array; avoids repeating preprocessor checks throughout the code.... -#if defined(PRODUCT_KRAKEN64) - #define HAS_RADIUS_PROXY 1 - static const auto (&radiusProxy)[NUM_PIXELS] = body; - static const uint8_t RADII_SCALE_DIVISOR { 1 }; // body[] values are already in range [0..255] - static const uint8_t RADII_SCALE_MULTIPLIER { 1 }; // body[] values are already in range [0..255] -#elif IS_FIBONACCI - #define HAS_RADIUS_PROXY 1 - - static const auto (&radiusProxy)[NUM_PIXELS] = physicalToFibonacci; - - static_assert( - ((NUM_PIXELS & (NUM_PIXELS-1)) == 0) || - (NUM_PIXELS == 34), - "RADII_SCALE_MULTIPLIER / RADII_SCALE_DIVISOR need updates to handle other non-power-of-two NUM_PIXELS" - ); - static const uint8_t RADII_SCALE_DIVISOR { (NUM_PIXELS <= 256u) ? 1 : (NUM_PIXELS / 256u) }; - static const uint8_t RADII_SCALE_MULTIPLIER { - (NUM_PIXELS >= 256) ? 1 : - (NUM_PIXELS == 34) ? 8 : // Careful .. use saturating multiplier or manually limit to 256... - ((NUM_PIXELS & (NUM_PIXELS-1)) == 0) ? (256u/NUM_PIXELS) : - 0 - }; - static_assert(RADII_SCALE_MULTIPLIER != 0, ""); -#else - #define HAS_RADIUS_PROXY 0 // default is that this is not supported.... -#endif - -#if HAS_RADIUS_PROXY - static_assert(HAS_COORDINATE_MAP, "HAS_RADIUS_PROXY also requires coordinate map"); -#endif +static_assert(RADII_SCALE_DIVISOR >= 1, ""); +static_assert(RADII_SCALE_MULTIPLIER >= 1, ""); +#define HAS_RADIUS_PROXY 1 // functions below wrapped by this ... leave defined for now +static_assert(HAS_COORDINATE_MAP, ""); +static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsX), ""); +static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsY), ""); +static_assert(NUM_PIXELS == ARRAY_SIZE2(angles), ""); #if IS_FIBONACCI // drawSpiralLine() uses angles[] and physicalToFibonacci[] void drawSpiralLine(uint8_t angle, int step, CRGB color) @@ -274,7 +323,6 @@ void anglePalette() { } #endif -// TODO - consider adding pre-computed radii[], enabled anytime HAS_COORDINATE_MAP is true #if HAS_RADIUS_PROXY // radiusPalette() uses radiusProxy[] void radiusPalette() { uint16_t hues = 1; @@ -422,7 +470,7 @@ void drawAnalogClock() { } #endif -// TODO: `drawSpiralAnalogClock13_21_and_34()` -- config to disable the seconds hand? +// TODO: `drawSpiralAnalogClock***()` -- config to disable the seconds hand? #if IS_FIBONACCI // drawSpiralAnalogClock*() calls drawSpiralLine(), which requires fibonacci void drawSpiralAnalogClock(uint8_t step_h, uint8_t step_m, uint8_t step_s) { @@ -486,5 +534,25 @@ void drawSpiralAnalogClock34_21_and_13() { } #endif +#if HAS_COORDINATE_MAP // radarSweepPalette() uses angles[] +void radarSweepPalette() { + fadeToBlackBy(leds, NUM_PIXELS, 64); + + uint8_t a = beat8(speed); + uint8_t b = beat88(1); + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint8_t angle = angles[i]; + + if(abs(angle - a) < 3) { + leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed)); + } + if(abs(angle - b) < 3) { + leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) + 85); + } + } +} +#endif + #endif // IS_FIBONACCI || HAS_COORDINATE_MAP diff --git a/esp8266-fastled-webserver/Noise.h b/esp8266-fastled-webserver/Noise.h index 0f568d14..2457ddbc 100644 --- a/esp8266-fastled-webserver/Noise.h +++ b/esp8266-fastled-webserver/Noise.h @@ -69,8 +69,21 @@ static const CRGBPalette16 blackAndBlueStripedPalette { // Additionally, you can manually define your own color palettes, or you can write // code that creates color palettes on the fly. -// TODO: Is Fib512 have a bug, because it uses `uint8_t` as data type for loop index, -// which will never be >= 512, and thus loop infinitely? +CRGB noiseXYZ(CRGBPalette16 palette, uint8_t hueReduce, int x, int y, int z) +{ + uint8_t data = inoise8(x, y, z); + // The range of the inoise8 function is roughly 16-238. + // These two operations expand those values out to roughly 0..255 + // You can comment them out if you want the raw noise data. + data = qsub8(data, 16); + data = qadd8(data, scale8(data, 39)); + + if (hueReduce > 0 && data >= hueReduce) { + data -= hueReduce; + } + + return ColorFromPalette(palette, data, 255, LINEARBLEND); +} void drawNoise(CRGBPalette16 palette, uint8_t hueReduce = 0) { @@ -81,25 +94,76 @@ void drawNoise(CRGBPalette16 palette, uint8_t hueReduce = 0) int xoffset = noisescale * x; int yoffset = noisescale * y; - uint8_t data = inoise8(x + xoffset + noisex, y + yoffset + noisey, noisez); + leds[i] = noiseXYZ(palette, hueReduce, x + xoffset + noisex, y + yoffset + noisey, noisez); + } - // The range of the inoise8 function is roughly 16-238. - // These two operations expand those values out to roughly 0..255 - // You can comment them out if you want the raw noise data. - data = qsub8(data, 16); - data = qadd8(data, scale8(data, 39)); + noisex += noisespeedx; + noisey += noisespeedy; + noisez += noisespeedz; +} - if (hueReduce > 0 && data >= hueReduce) - data -= hueReduce; +#if HAS_POLAR_COORDS // change to "HAS_CONCENTRIC_RINGS" ? - leds[i] = ColorFromPalette(palette, data, 255, LINEARBLEND); - } +// TODO: The calculations for x/y in drawPolarNoise() depend only upon constant array values. +// Pre-calculate those, and define a proxy for noise() routine that points to this +// pre-calculated array. Then, the code is identical for all noise() functions, differing +// only in the X/Y arrays and palette used. +// drawPolarNoise() uses rings[] +void drawPolarNoise(CRGBPalette16 palette, uint8_t hueReduce = 0) +{ + for (uint8_t ringIndex = 0; ringIndex < ringCount; ringIndex++) { // y == proxy for radius + uint16_t ringStart = rings[ringIndex][0]; + uint16_t ringEnd = rings[ringIndex][1]; + + for (uint16_t i = ringStart; i <= ringEnd; i++) { // x + uint8_t x = (i - ringStart) * (256 / (ringEnd - ringStart)); // proxy for angle[]? + uint8_t y = ringIndex * (128 / ringCount); // 128 / 20 == 6 ... or about half the total range ... could use (radius[] / 2)? + + int xoffset = noisescale * x; + int yoffset = noisescale * y; + + leds[i] = noiseXYZ(palette, hueReduce, x + xoffset + noisex, y + yoffset + noisey, noisez); + } + } + // for (uint8_t ringIndex = 1; ringIndex < ringCount; ringIndex++) { + // uint16_t ringStart = rings[ringIndex][0]; + // uint16_t ringEnd = rings[ringIndex][1]; + // // blend the first pixel in the ring into the last + // nblend(leds[ringStart], leds[ringEnd], 192); + // nblend(leds[ringStart + 1], leds[ringEnd - 1], 128); + // nblend(leds[ringStart + 2], leds[ringEnd - 2], 64); + // } + noisex += noisespeedx; noisey += noisespeedy; noisez += noisespeedz; } +#endif // HAS_POLAR_COORDS + +#if HAS_POLAR_COORDS // uses drawPolarNoise(), which uses rings[] +// TODO: Check if gradientPalettePolarNoise() is equivalent to angleGradientPalette()? +void gradientPalettePolarNoise() { + noisespeedx = 4; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(gCurrentPalette); +} +#endif +#if HAS_POLAR_COORDS // palettePolarNoise() uses drawPolarNoise(), which uses rings[] +void palettePolarNoise() { + noisespeedx = 9; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(palettes[currentPaletteIndex]); +} +#endif + void rainbowNoise() { noisespeedx = 0; noisespeedy = -1; @@ -109,6 +173,17 @@ void rainbowNoise() { drawNoise(RainbowColors_p); } +#if HAS_POLAR_COORDS // rainbowPolarNoise() uses drawPolarNoise(), which uses rings[] +void rainbowPolarNoise() { + noisespeedx = 0; + noisespeedy = 2; + noisespeedz = 0; + noisescale = 0; + colorLoop = 0; + drawPolarNoise(RainbowColors_p); +} +#endif // HAS_POLAR_COORDS + void rainbowStripeNoise() { noisespeedx = 0; noisespeedy = -2; @@ -118,6 +193,17 @@ void rainbowStripeNoise() { drawNoise(RainbowStripeColors_p); } +#if HAS_POLAR_COORDS // rainbowStripePolarNoise() uses drawPolarNoise(), which uses rings[] +void rainbowStripePolarNoise() { + noisespeedx = 0; + noisespeedy = 2; + noisespeedz = 0; + noisescale = 0; + colorLoop = 0; + drawPolarNoise(RainbowStripeColors_p); +} +#endif + void partyNoise() { noisespeedx = -9; noisespeedy = 0; @@ -127,6 +213,17 @@ void partyNoise() { drawNoise(PartyColors_p); } +#if HAS_POLAR_COORDS // partyPolarNoise() uses drawPolarNoise(), which uses rings[] +void partyPolarNoise() { + noisespeedx = 9; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(PartyColors_p); +} +#endif + void forestNoise() { noisespeedx = -9; noisespeedy = 0; @@ -136,6 +233,17 @@ void forestNoise() { drawNoise(ForestColors_p); } +#if HAS_POLAR_COORDS // forestPolarNoise() uses drawPolarNoise(), which uses rings[] +void forestPolarNoise() { + noisespeedx = 9; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(ForestColors_p); +} +#endif + void cloudNoise() { noisespeedx = -2; noisespeedy = 0; @@ -145,6 +253,17 @@ void cloudNoise() { drawNoise(CloudColors_p); } +#if HAS_POLAR_COORDS // cloudPolarNoise() uses drawPolarNoise(), which uses rings[] +void cloudPolarNoise() { + noisespeedx = 2; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 0; + colorLoop = 0; + drawPolarNoise(CloudColors_p); +} +#endif + void fireNoise() { noisespeedx = 0; // 24; noisespeedy = -32; @@ -154,6 +273,22 @@ void fireNoise() { drawNoise(HeatColors_p, 60); } +#if HAS_POLAR_COORDS // firePolarNoise() uses drawPolarNoise(), which uses rings[] +void firePolarNoise() { +// noisespeedx = 0; // 24; +// noisespeedy = -24; +// noisespeedz = 0; +// noisescale = 4; +// colorLoop = 0; + noisespeedx = 0; // 24; + noisespeedy = -32; + noisespeedz = 0; + noisescale = 4; + colorLoop = 0; + drawPolarNoise(HeatColors_p, 60); +} +#endif + void fireNoise2() { noisespeedx = 0; noisespeedy = -8; @@ -163,6 +298,22 @@ void fireNoise2() { drawNoise(HeatColors_p); } +#if HAS_POLAR_COORDS // firePolarNoise2() uses drawPolarNoise(), which uses rings[] +void firePolarNoise2() { +// noisespeedx = 0; +// noisespeedy = -8; +// noisespeedz = 4; +// noisescale = 1; +// colorLoop = 0; + noisespeedx = 0; + noisespeedy = -4; + noisespeedz = 4; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(HeatColors_p); +} +#endif + void lavaNoise() { noisespeedx = 0; noisespeedy = -1; @@ -172,6 +323,17 @@ void lavaNoise() { drawNoise(LavaColors_p); } +#if HAS_POLAR_COORDS // lavaPolarNoise() uses drawPolarNoise(), which uses rings[] +void lavaPolarNoise() { + noisespeedx = 0; + noisespeedy = -1; + noisespeedz = 1; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(LavaColors_p); +} +#endif + void oceanNoise() { noisespeedx = -2; noisespeedy = 0; @@ -181,6 +343,17 @@ void oceanNoise() { drawNoise(OceanColors_p); } +#if HAS_POLAR_COORDS // oceanPolarNoise() uses drawPolarNoise(), which uses rings[] +void oceanPolarNoise() { + noisespeedx = -1; // beatsin8(6, 0, 2) - 1; + noisespeedy = 0; + noisespeedz = 1; + noisescale = 0; + colorLoop = 0; + drawPolarNoise(OceanColors_p); +} +#endif + void blackAndWhiteNoise() { noisespeedx = -12; noisespeedy = 0; @@ -190,6 +363,17 @@ void blackAndWhiteNoise() { drawNoise(blackAndWhiteStripedPalette); } +#if HAS_POLAR_COORDS // blackAndWhitePolarNoise() uses drawPolarNoise(), which uses rings[] +void blackAndWhitePolarNoise() { + noisespeedx = -4; // beatsin8(8, 0, 9) - 4; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 0; + colorLoop = 0; + drawPolarNoise(blackAndWhiteStripedPalette); +} +#endif + void blackAndBlueNoise() { noisespeedx = 0; noisespeedy = 8; @@ -199,5 +383,15 @@ void blackAndBlueNoise() { drawNoise(blackAndBlueStripedPalette); } +#if HAS_POLAR_COORDS // blackAndBluePolarNoise() uses drawPolarNoise(), which uses rings[] +void blackAndBluePolarNoise() { + noisespeedx = 0; + noisespeedy = -8; // beatsin8(8, 0, 16) - 8; + noisespeedz = 0; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(blackAndBlueStripedPalette); +} +#endif #endif // HAS_COORDINATE_MAP \ No newline at end of file diff --git a/esp8266-fastled-webserver/config.h b/esp8266-fastled-webserver/config.h index 0e9a89a6..f162bc90 100644 --- a/esp8266-fastled-webserver/config.h +++ b/esp8266-fastled-webserver/config.h @@ -34,8 +34,8 @@ // #define PRODUCT_FIBONACCI64_NANO // 33mm, SK6805-EC15, ~5mA/pixel // #define PRODUCT_FIBONACCI32 // #define PRODUCT_KRAKEN64 -#define PRODUCT_ESP8266_THING // aka parallel (6-output) - +// #define PRODUCT_ESP8266_THING // aka parallel (6-output) +#define PRODUCT_1628_RINGS // //////////////////////////////////////////////////////////////////////////////////////////////////// // Additional configuration options ... defaults shown @@ -146,6 +146,9 @@ #if !defined(HAS_POLAR_COORDS) || ((HAS_POLAR_COORDS != 0) && (HAS_POLAR_COORDS != 1)) #error "HAS_POLAR_COORDS must be defined to zero or one" #endif + #if HAS_POLAR_COORDS && (!HAS_COORDINATE_MAP) + #error "HAS_POLAR_COORDS is true, so HAS_COORDINATE_MAP must also be true (but is not)" + #endif #if !defined(PARALLEL_OUTPUT_CHANNELS) #error "PARALLEL_OUTPUT_CHANNELS must be defined" #elif (PARALLEL_OUTPUT_CHANNELS == 1) diff --git a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino index b7e90de4..f2b9dd40 100644 --- a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino +++ b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino @@ -117,6 +117,25 @@ PatternAndNameList patterns = { { colorWaves, "Color Waves" }, +#if HAS_POLAR_COORDS // really a wrong name... and likely doing way more computation than necessary + { radarSweepPalette, "Radar Sweep Palette" }, + // noise patterns (XY and 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" }, + { rainbowStripeNoise, "Rainbow Stripe 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" }, @@ -1038,6 +1057,47 @@ void loop() { // TODO: Update magic number from 0x55 to 0xAA (or 0x96 or 0x69) +void readSettings1628Rings() +{ + // 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) { + return; + } + + brightness = EEPROM.read(0); + + currentPatternIndex = EEPROM.read(1); + if (currentPatternIndex >= patternCount) { + currentPatternIndex = patternCount - 1; + } + + byte r = EEPROM.read(2); + byte g = EEPROM.read(3); + byte b = EEPROM.read(4); + + if (r == 0 && g == 0 && b == 0) + { + } + else + { + solidColor = CRGB(r, g, b); + } + + power = EEPROM.read(5); + + autoplay = EEPROM.read(6); + autoplayDuration = EEPROM.read(7); + + currentPaletteIndex = EEPROM.read(8); + if (currentPaletteIndex >= paletteCount) { + currentPaletteIndex = paletteCount - 1; + } + showClock = EEPROM.read(9); + clockBackgroundFade = EEPROM.read(10); + +} void readSettingsEsp8266Thing() // aka parallel { // check for "magic number" so we know settings have been written to EEPROM @@ -1395,7 +1455,9 @@ void readSettingsDefaultProduct() } void readSettings() { - #if defined(PRODUCT_ESP8266_THING) + #if defined (PRODUCT_1628_RINGS) + readSettings1628Rings(); + #elif defined(PRODUCT_ESP8266_THING) readSettingsEsp8266Thing(); #elif defined(PRODUCT_KRAKEN64) readSettingsKraken64(); @@ -1415,7 +1477,22 @@ void readSettings() { #error "readSettings() not defined for product?" #endif } +void writeAndCommitSettings1628Rings() { + EEPROM.write(0, brightness); + EEPROM.write(1, currentPatternIndex); + EEPROM.write(2, solidColor.r); + EEPROM.write(3, solidColor.g); + EEPROM.write(4, solidColor.b); + EEPROM.write(5, power); + EEPROM.write(6, autoplay); + EEPROM.write(7, autoplayDuration); + EEPROM.write(8, currentPaletteIndex); + EEPROM.write(9, showClock); + EEPROM.write(10, clockBackgroundFade); + EEPROM.write(511, 55); + EEPROM.commit(); +} void writeAndCommitSettingsEsp8266Thing() // aka parallel { EEPROM.write(0, brightness); @@ -1571,7 +1648,9 @@ void writeAndCommitSettingsDefaultProduct() void writeAndCommitSettings() { - #if defined(PRODUCT_ESP8266_THING) + #if defined (PRODUCT_1628_RINGS) + writeAndCommitSettings1628Rings(); + #elif defined(PRODUCT_ESP8266_THING) writeAndCommitSettingsEsp8266Thing(); #elif defined(PRODUCT_KRAKEN64) writeAndCommitSettingsKraken64(); @@ -2084,9 +2163,6 @@ void palettetest( CRGB* ledarray, uint16_t numleds, const CRGBPalette16& gCurren fill_palette( ledarray, numleds, startindex, (256 / NUM_PIXELS) + 1, gCurrentPalette, 255, LINEARBLEND); } - -// TODO - swirlFibonacci(): Disable if NUM_PIXELS < 128? - #if IS_FIBONACCI // swirlFibonacci() uses physicalToFibonacci and angles void swirlFibonacci() { @@ -2118,8 +2194,6 @@ void swirlFibonacci() { } #endif -// TODO - fireFibonacci(): Disable if NUM_PIXELS < 128? - #if IS_FIBONACCI // fireFibonacci() uses coordsX/coordsY // TODO: combine with normal fire effect void fireFibonacci() { @@ -2134,8 +2208,6 @@ void fireFibonacci() { } #endif -// TODO - waterFibonacci(): Disable if NUM_PIXELS < 128? - #if IS_FIBONACCI // waterFibonacci() uses coordsX/coordsY // TODO: combine with normal water effect void waterFibonacci() { @@ -2150,8 +2222,6 @@ void waterFibonacci() { } #endif -// TODO - emitterFibonacci(): Disable if NUM_PIXELS < 128? - #if IS_FIBONACCI // emitterFibonacci() uses angle, antialiasPixelAR() /** * Emits arcs of color spreading out from the center to the edge of the disc. diff --git a/esp8266-fastled-webserver/include/configs/product/1628rings.h b/esp8266-fastled-webserver/include/configs/product/1628rings.h index 6180cefe..af3b02d4 100644 --- a/esp8266-fastled-webserver/include/configs/product/1628rings.h +++ b/esp8266-fastled-webserver/include/configs/product/1628rings.h @@ -57,12 +57,13 @@ #define IS_FIBONACCI 0 #endif #if !defined(HAS_COORDINATE_MAP) - #define HAS_COORDINATE_MAP 0 + #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) +#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 From 77a3503318db66eec14b6e5ea138c36ebc2b647f Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Wed, 20 Oct 2021 16:57:12 -0700 Subject: [PATCH 08/16] Get 1628_RINGS product compiling --- esp8266-fastled-webserver/Map.h | 144 +++++++++--- esp8266-fastled-webserver/Noise.h | 218 +++++++++++++++++- esp8266-fastled-webserver/config.h | 7 +- .../esp8266-fastled-webserver.ino | 92 +++++++- .../include/configs/product/1628rings.h | 5 +- 5 files changed, 401 insertions(+), 65 deletions(-) diff --git a/esp8266-fastled-webserver/Map.h b/esp8266-fastled-webserver/Map.h index f77f12c7..8c7bb03a 100644 --- a/esp8266-fastled-webserver/Map.h +++ b/esp8266-fastled-webserver/Map.h @@ -57,24 +57,36 @@ const uint8_t coordsX[NUM_PIXELS] { 170, 178, 185, 191, 196, 199, 202, 202, 202, 200, 196, 191, 184, 175, 161, 132, 148, 166, 176, 183, 188, 190, 192, 191, 190, 186, 182, 176, 170, 162, 153, 125, 136, 145, 154, 161, 168, 173, 177, 180, 181, 181, 178, 174, 167, 155, 139, 157, 164, 169, 170, 170, 168, 165, 160, 154, 147, 139, 129, 119, 109, 82, 93, 104, 114, 124, 132, 140, 147, 152, 157, 159, 160, 159, 155, 145, 145, 150, 150, 149, 146, 141, 135, 127, 119, 110, 100, 90, 79, 68, 57, 45, 56, 66, 77, 87, 97, 107, 115, 123, 130, 135, 139, 142, 141, 136, 134, 134, 131, 126, 120, 113, 105, 96, 86, 76, 66, 56, 45, 35, 25, 18, 27, 37, 47, 57, 67, 77, 86, 95, 104, 112, 119, 124, 128, 129, 125, 120, 113, 105, 97, 88, 78, 69, 59, 50, 40, 31, 22, 14, 6, 0, 6, 12, 19, 27, 35, 44, 54, 63, 73, 82, 91, 101, 109, 118, 121, 108, 98, 88, 78, 69, 59, 50, 41, 33, 25, 18, 12, 7, 3, 6, 8, 11, 15, 20, 26, 33, 40, 48, 57, 67, 77, 87, 98, 111, 102, 89, 77, 67, 58, 49, 41, 34, 28, 23, 19, 16, 15, 14, 15, 26, 24, 23, 24, 26, 28, 33, 38, 44, 51, 60, 69, 80, 93, 111, 100, 85, 73, 64, 55, 49, 43, 39, 36, 34, 33, 34, 36, 39, 43, 58, 53, 49, 45, 44, 43, 44, 46, 50, 55, 61, 69, 79, 93, 116, 104, 87, 76, 68, 62, 58, 55, 54, 54, 55, 58, 62, 68, 74, 82, 108, 99, 90, 83, 77, 72, 68, 65, 64, 65, 67, 70, 76, 85, 97, 112, 94, 85, 80, 76, 75, 75, 77, 81, 85, 91, 98, 106, 115, 125, 153, 142, 131, 122, 113, 105, 99, 93, 89, 87, 85, 86, 89, 95, 106, 123, 105, 99, 96, 96, 98, 101, 106, 112, 119, 128, 137, 147, 157, 168, 180, 193, 182, 171, 161, 151, 141, 133, 125, 118, 113, 108, 106, 106, 108, 115, 116, 114, 115, 118, 123, 129, 137, 145, 154, 164, 174, 184, 195, 206, 216, 226, 216, 205, 195, 185, 175, 165, 156, 147, 139, 133, 127, 123, 121, 124, 127, 129, 134, 141, 148, 156, 165, 174, 184, 194, 204, 214, 224, 233, 242, 253, 246, 238, 229, 221, 211, 202, 192, 182, 173, 164, 155, 147, 140, 133, 134, 142, 151, 160, 169, 179, 188, 198, 207, 216, 225, 233, 241, 247, 253, 255, 251, 247, 241, 234, 227, 219, 210, 201, 192, 182, 173, 163, 153, 142, 134, 151, 163, 174, 184, 194, 203, 212, 220, 227, 233, 239, 243, 247, 249, 242, 242, 241, 238, 235, 230, 225, 218, 211, 203, 194, 184, 173, 161, 146, 155, 170, 182, 192, 201, 208, 215, 221, 226, 229, 231, 232, 232, 231, 228, 215, 219, 221, 223, 223, 221, 219, 215, 210, 204, 197, 188, 177, 164, 144, 154, 170, 182, 191, 198, 204, 208, 211, 212, 213, 212, 209, 205, 200, 194 }; const uint8_t coordsY[NUM_PIXELS] { 6, 14, 22, 31, 41, 50, 60, 70, 80, 89, 98, 106, 114, 120, 125, 128, 124, 116, 109, 101, 92, 82, 73, 63, 54, 44, 35, 27, 18, 11, 4, 0, 5, 10, 17, 24, 32, 40, 49, 59, 68, 78, 87, 97, 106, 116, 121, 106, 95, 85, 75, 65, 56, 47, 38, 31, 24, 17, 12, 7, 4, 10, 10, 13, 16, 20, 25, 31, 39, 46, 55, 64, 74, 85, 96, 111, 101, 87, 76, 65, 56, 48, 41, 34, 29, 25, 21, 20, 19, 19, 21, 33, 30, 29, 28, 29, 31, 34, 39, 45, 51, 59, 69, 79, 92, 111, 101, 85, 73, 64, 56, 50, 45, 41, 39, 38, 38, 40, 43, 47, 52, 68, 62, 56, 53, 50, 49, 49, 50, 53, 57, 63, 70, 80, 94, 119, 106, 89, 78, 70, 65, 61, 59, 59, 60, 62, 66, 71, 77, 84, 92, 119, 109, 100, 92, 85, 80, 75, 72, 70, 70, 71, 74, 79, 87, 99, 114, 97, 88, 83, 81, 80, 81, 84, 88, 94, 100, 108, 116, 126, 136, 163, 152, 142, 132, 123, 114, 107, 101, 96, 93, 91, 91, 93, 98, 108, 108, 102, 101, 101, 104, 108, 114, 120, 128, 137, 146, 157, 167, 178, 190, 203, 192, 181, 170, 160, 150, 141, 133, 126, 119, 115, 111, 110, 111, 118, 119, 118, 120, 124, 130, 136, 144, 153, 162, 172, 182, 193, 203, 214, 224, 232, 223, 213, 202, 192, 182, 172, 163, 154, 146, 139, 132, 128, 125, 126, 129, 133, 139, 146, 154, 162, 172, 181, 191, 201, 210, 220, 229, 238, 246, 255, 249, 242, 234, 225, 216, 207, 197, 188, 178, 169, 160, 151, 143, 136, 135, 145, 155, 164, 174, 183, 193, 202, 211, 220, 228, 236, 243, 249, 254, 253, 250, 246, 242, 236, 229, 222, 213, 205, 196, 186, 176, 166, 155, 143, 133, 153, 166, 177, 187, 196, 205, 214, 221, 228, 234, 238, 242, 245, 246, 246, 236, 237, 237, 236, 233, 229, 225, 219, 212, 204, 195, 186, 175, 162, 146, 156, 171, 182, 192, 201, 208, 214, 220, 223, 226, 228, 228, 227, 224, 221, 207, 211, 215, 217, 218, 218, 216, 213, 209, 203, 196, 187, 177, 164, 142, 153, 170, 181, 190, 196, 201, 205, 207, 208, 207, 205, 202, 197, 191, 184, 159, 168, 176, 182, 188, 192, 195, 197, 197, 196, 193, 189, 182, 173, 160, 146, 164, 173, 180, 184, 186, 186, 185, 183, 179, 174, 167, 160, 151, 142, 114, 125, 135, 144, 152, 159, 165, 170, 173, 175, 176, 174, 171, 164, 153, 136, 154, 161, 164, 165, 164, 162, 157, 152, 145, 138, 129, 119, 109, 98, 72, 83, 94, 105, 114, 124, 132, 139, 145, 150, 153, 155, 155, 152, 143, 142, 146, 146, 143, 139, 134, 127, 119, 110, 101, 91, 81, 70, 59, 48, 37, 48, 58, 69, 79, 89, 99, 108, 116, 123, 129, 134, 137, 138, 134, 132, 130, 126, 121, 114, 106, 98, 88, 79, 69, 59, 48, 38, 29, 19 }; const uint8_t angles[NUM_PIXELS] { 205, 208, 211, 215, 218, 221, 225, 228, 231, 235, 238, 242, 245, 248, 252, 255, 246, 243, 239, 236, 233, 229, 226, 223, 219, 216, 213, 209, 206, 203, 199, 190, 194, 197, 200, 204, 207, 211, 214, 217, 221, 224, 227, 231, 234, 237, 232, 229, 225, 222, 219, 215, 212, 208, 205, 202, 198, 195, 192, 188, 185, 176, 180, 183, 186, 190, 193, 196, 200, 203, 206, 210, 213, 216, 220, 223, 214, 211, 208, 204, 201, 198, 194, 191, 188, 184, 181, 177, 174, 171, 167, 162, 165, 169, 172, 175, 179, 182, 185, 189, 192, 196, 199, 202, 206, 209, 200, 197, 193, 190, 187, 183, 180, 177, 173, 170, 167, 163, 160, 157, 153, 148, 151, 154, 158, 161, 165, 168, 171, 175, 178, 181, 185, 188, 191, 195, 186, 183, 179, 176, 173, 169, 166, 162, 159, 156, 152, 149, 146, 142, 139, 130, 133, 137, 140, 144, 147, 150, 154, 157, 160, 164, 167, 170, 174, 177, 172, 168, 165, 162, 158, 155, 152, 148, 145, 141, 138, 135, 131, 128, 125, 116, 119, 123, 126, 129, 133, 136, 139, 143, 146, 149, 153, 156, 160, 163, 154, 151, 147, 144, 141, 137, 134, 131, 127, 124, 121, 117, 114, 110, 107, 102, 105, 108, 112, 115, 118, 122, 125, 129, 132, 135, 139, 142, 145, 149, 140, 137, 133, 130, 126, 123, 120, 116, 113, 110, 106, 103, 100, 96, 93, 87, 91, 94, 98, 101, 104, 108, 111, 114, 118, 121, 124, 128, 131, 134, 126, 122, 119, 116, 112, 109, 106, 102, 99, 95, 92, 89, 85, 82, 79, 70, 73, 77, 80, 83, 87, 90, 93, 97, 100, 103, 107, 110, 114, 117, 111, 108, 105, 101, 98, 95, 91, 88, 85, 81, 78, 74, 71, 68, 64, 56, 59, 62, 66, 69, 72, 76, 79, 82, 86, 89, 93, 96, 99, 103, 97, 94, 90, 87, 84, 80, 77, 74, 70, 67, 64, 60, 57, 54, 50, 47, 41, 45, 48, 51, 55, 58, 62, 65, 68, 72, 75, 78, 82, 85, 88, 80, 76, 73, 70, 66, 63, 59, 56, 53, 49, 46, 43, 39, 36, 33, 27, 31, 34, 37, 41, 44, 47, 51, 54, 57, 61, 64, 67, 71, 74, 65, 62, 59, 55, 52, 49, 45, 42, 39, 35, 32, 28, 25, 22, 18, 10, 13, 16, 20, 23, 26, 30, 33, 36, 40, 43, 47, 50, 53, 57, 51, 48, 44, 41, 38, 34, 31, 28, 24, 21, 18, 14, 11, 8, 4, 251, 254, 2, 5, 9, 12, 16, 19, 22, 26, 29, 32, 36, 39, 42, 37, 34, 30, 27, 24, 20, 17, 13, 10, 7, 3, 0, 252, 249, 245, 236, 240, 243, 247, 250, 253, 1, 5, 8, 11, 15, 18, 21, 25, 28, 19, 16, 13, 9, 6, 3, 255, 251, 248, 244, 241, 238, 234, 231, 228, 222, 226, 229, 232, 236, 239, 242, 246, 249, 252, 0, 4, 7, 11, 14, 5, 2, 254, 250, 247, 244, 240, 237, 234, 230, 227, 223, 220, 217, 213 }; + static const auto (&radiusProxy)[NUM_PIXELS] = physicalToFibonacci; + static const uint8_t RADII_SCALE_DIVISOR { 2 }; + static const uint8_t RADII_SCALE_MULTIPLIER { 1 }; #elif defined(PRODUCT_FIBONACCI256) const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 39, 52, 65, 78, 91, 104, 117, 130, 143, 156, 169, 182, 195, 208, 221, 234, 247, 252, 239, 226, 213, 200, 187, 174, 161, 148, 135, 122, 109, 96, 83, 70, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 75, 88, 101, 114, 127, 140, 153, 166, 179, 192, 205, 218, 231, 244, 249, 236, 223, 210, 197, 184, 171, 158, 145, 132, 119, 106, 93, 80, 67, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 137, 150, 163, 176, 189, 202, 215, 228, 241, 254, 246, 233, 220, 207, 194, 181, 168, 155, 142, 129, 116, 103, 90, 77, 64, 51, 38, 25, 12, 4, 17, 30, 43, 56, 69, 82, 95, 108, 121, 134, 147, 160, 173, 186, 199, 212, 225, 238, 251, 243, 230, 217, 204, 191, 178, 165, 152, 139, 126, 113, 100, 87, 74, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 66, 79, 92, 105, 118, 131, 144, 157, 170, 183, 196, 209, 222, 235, 248, 253, 240, 227, 214, 201, 188, 175, 162, 149, 136, 123, 110, 97, 84, 71, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 76, 89, 102, 115, 128, 141, 154, 167, 180, 193, 206, 219, 232, 245, 250, 237, 224, 211, 198, 185, 172, 159, 146, 133, 120, 107, 94, 81, 68, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60, 73, 86, 99, 112, 125, 138, 151, 164, 177, 190, 203, 216, 229, 242, 255 }; const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 157, 78, 235, 118, 39, 196, 79, 236, 156, 40, 197, 117, 1, 158, 77, 234, 119, 38, 195, 80, 237, 155, 41, 198, 116, 2, 159, 76, 233, 120, 37, 194, 81, 238, 154, 42, 199, 115, 3, 160, 75, 232, 121, 36, 193, 82, 239, 153, 43, 200, 114, 4, 161, 74, 231, 122, 35, 192, 83, 240, 152, 44, 201, 113, 5, 162, 73, 230, 123, 34, 191, 84, 241, 151, 45, 202, 112, 6, 163, 72, 229, 124, 33, 190, 85, 242, 150, 46, 203, 111, 7, 164, 71, 228, 125, 32, 189, 86, 243, 149, 47, 204, 110, 8, 165, 70, 227, 126, 31, 188, 87, 244, 148, 48, 205, 109, 9, 166, 69, 226, 127, 30, 187, 88, 245, 147, 49, 206, 108, 10, 167, 68, 225, 128, 29, 186, 89, 246, 146, 50, 207, 107, 11, 168, 67, 224, 129, 28, 185, 90, 247, 145, 51, 208, 106, 12, 169, 66, 223, 130, 27, 184, 91, 248, 144, 52, 209, 105, 13, 170, 65, 222, 131, 26, 183, 92, 249, 143, 53, 210, 104, 14, 171, 64, 221, 132, 25, 182, 93, 250, 142, 54, 211, 103, 15, 172, 63, 220, 133, 24, 181, 94, 251, 141, 55, 212, 102, 16, 173, 62, 219, 134, 23, 180, 95, 252, 140, 56, 213, 101, 17, 174, 61, 218, 135, 22, 179, 96, 253, 139, 57, 214, 100, 18, 175, 60, 217, 136, 21, 178, 97, 254, 138, 58, 215, 99, 19, 176, 59, 216, 137, 20, 177, 98, 255 }; const uint8_t coordsX[NUM_PIXELS] { 133, 156, 165, 168, 165, 158, 147, 132, 114, 95, 76, 57, 41, 28, 19, 15, 17, 24, 37, 56, 123, 96, 73, 53, 38, 28, 24, 25, 31, 41, 55, 71, 89, 106, 122, 136, 146, 152, 152, 143, 138, 136, 128, 115, 101, 85, 70, 56, 44, 37, 33, 34, 41, 53, 69, 90, 114, 140, 167, 226, 204, 180, 154, 129, 106, 85, 67, 54, 46, 43, 44, 50, 60, 72, 86, 100, 113, 123, 128, 117, 104, 90, 78, 67, 59, 54, 54, 59, 68, 82, 100, 121, 143, 167, 191, 212, 231, 246, 255, 251, 251, 245, 233, 218, 199, 178, 156, 134, 114, 96, 82, 73, 67, 66, 70, 78, 89, 103, 111, 94, 84, 80, 81, 86, 96, 109, 126, 145, 165, 185, 204, 220, 233, 241, 244, 241, 232, 217, 179, 201, 217, 229, 235, 235, 230, 220, 207, 190, 172, 154, 136, 121, 108, 99, 95, 96, 104, 120, 110, 111, 118, 130, 144, 160, 176, 192, 206, 217, 224, 227, 224, 216, 202, 184, 162, 137, 110, 44, 68, 94, 120, 145, 168, 187, 202, 212, 216, 216, 212, 203, 191, 177, 162, 148, 135, 126, 122, 136, 147, 161, 174, 186, 197, 204, 206, 205, 198, 187, 172, 152, 130, 106, 81, 58, 36, 17, 0, 5, 15, 30, 49, 71, 93, 116, 138, 157, 173, 185, 192, 195, 193, 187, 178, 166, 152, 137, 149, 164, 175, 180, 182, 179, 171, 159, 143, 125, 105, 83, 63, 44, 28, 16, 9, 7, 12, 23 }; const uint8_t coordsY[NUM_PIXELS] { 126, 120, 109, 96, 82, 69, 57, 49, 45, 45, 50, 59, 74, 92, 114, 138, 163, 188, 211, 231, 255, 248, 235, 218, 198, 175, 152, 129, 107, 89, 74, 63, 57, 56, 59, 66, 76, 88, 102, 116, 103, 88, 77, 71, 68, 70, 77, 88, 103, 121, 141, 163, 184, 205, 222, 236, 245, 249, 247, 208, 224, 235, 241, 240, 234, 223, 209, 191, 172, 152, 132, 115, 101, 90, 84, 82, 86, 95, 114, 107, 98, 98, 103, 112, 126, 142, 159, 177, 195, 210, 222, 230, 233, 230, 223, 209, 191, 168, 142, 98, 125, 151, 174, 194, 209, 219, 223, 223, 218, 208, 195, 180, 164, 148, 134, 122, 114, 112, 123, 128, 138, 151, 165, 180, 193, 203, 211, 214, 212, 206, 194, 178, 158, 134, 109, 83, 58, 35, 11, 28, 48, 71, 95, 120, 142, 163, 179, 192, 200, 203, 202, 196, 187, 175, 162, 148, 136, 133, 152, 166, 177, 186, 190, 191, 187, 178, 165, 148, 128, 107, 84, 62, 41, 24, 11, 2, 0, 28, 16, 9, 8, 13, 23, 37, 55, 75, 96, 116, 135, 151, 164, 173, 177, 177, 172, 162, 146, 153, 161, 163, 160, 152, 139, 124, 106, 87, 69, 51, 36, 25, 18, 16, 20, 29, 44, 64, 133, 106, 81, 60, 44, 32, 26, 25, 29, 38, 50, 65, 82, 99, 115, 129, 140, 147, 148, 138, 134, 131, 122, 110, 95, 80, 65, 52, 42, 36, 34, 37, 45, 59, 77, 98, 123, 149, 176, 202 }; const uint8_t angles[NUM_PIXELS] { 0, 247, 238, 229, 220, 211, 203, 194, 185, 176, 167, 159, 150, 141, 132, 123, 115, 106, 97, 88, 65, 74, 83, 92, 100, 109, 118, 127, 136, 144, 153, 162, 171, 180, 188, 197, 206, 215, 224, 232, 209, 201, 192, 183, 174, 165, 157, 148, 139, 130, 121, 113, 104, 95, 86, 77, 69, 60, 51, 28, 37, 46, 54, 63, 72, 81, 90, 98, 107, 116, 125, 134, 142, 151, 160, 169, 178, 186, 195, 172, 163, 155, 146, 137, 128, 119, 111, 102, 93, 84, 75, 67, 58, 49, 40, 31, 23, 14, 5, 246, 255, 8, 17, 26, 35, 44, 52, 61, 70, 79, 88, 96, 105, 114, 123, 132, 140, 149, 135, 126, 117, 108, 100, 91, 82, 73, 64, 56, 47, 38, 29, 20, 12, 3, 250, 241, 232, 223, 209, 218, 227, 235, 244, 253, 6, 15, 24, 33, 41, 50, 59, 68, 77, 85, 94, 103, 112, 98, 89, 80, 71, 62, 54, 45, 36, 27, 18, 10, 1, 247, 239, 230, 221, 212, 203, 195, 186, 163, 172, 180, 189, 198, 207, 216, 224, 233, 242, 251, 4, 13, 22, 31, 39, 48, 57, 66, 75, 52, 43, 34, 25, 16, 8, 254, 245, 237, 228, 219, 210, 201, 193, 184, 175, 166, 157, 149, 126, 134, 143, 152, 161, 170, 178, 187, 196, 205, 214, 222, 231, 240, 249, 2, 11, 20, 28, 37, 14, 5, 252, 243, 235, 226, 217, 208, 199, 191, 182, 173, 164, 155, 147, 138, 129, 120, 111, 103 }; + static const auto (&radiusProxy)[NUM_PIXELS] = physicalToFibonacci; + static const uint8_t RADII_SCALE_DIVISOR { 1 }; + static const uint8_t RADII_SCALE_MULTIPLIER { 1 }; #elif defined(PRODUCT_FIBONACCI128) const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 39, 52, 65, 78, 91, 104, 117, 122, 109, 96, 83, 70, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 75, 88, 101, 114, 127, 119, 106, 93, 80, 67, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 72, 85, 98, 111, 124, 116, 103, 90, 77, 64, 51, 38, 25, 12, 4, 17, 30, 43, 56, 69, 82, 95, 108, 121, 126, 113, 100, 87, 74, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 66, 79, 92, 105, 118, 123, 110, 97, 84, 71, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 76, 89, 102, 115, 120, 107, 94, 81, 68, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60, 73, 86, 99, 112, 125 }; const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 79, 39, 117, 59, 19, 98, 40, 118, 78, 20, 99, 58, 1, 80, 38, 116, 60, 18, 97, 41, 119, 77, 21, 100, 57, 2, 81, 37, 115, 61, 17, 96, 42, 120, 76, 22, 101, 56, 3, 82, 36, 114, 62, 16, 95, 43, 121, 75, 23, 102, 55, 4, 83, 35, 113, 63, 15, 94, 44, 122, 74, 24, 103, 54, 5, 84, 34, 112, 64, 14, 93, 45, 123, 73, 25, 104, 53, 6, 85, 33, 111, 65, 13, 92, 46, 124, 72, 26, 105, 52, 7, 86, 32, 110, 66, 12, 91, 47, 125, 71, 27, 106, 51, 8, 87, 31, 109, 67, 11, 90, 48, 126, 70, 28, 107, 50, 9, 88, 30, 108, 68, 10, 89, 49, 127, 69, 29 }; const uint8_t coordsX[NUM_PIXELS] { 137, 170, 182, 186, 182, 172, 156, 135, 110, 83, 26, 49, 74, 99, 121, 141, 155, 164, 164, 151, 145, 141, 129, 112, 91, 69, 47, 27, 11, 0, 9, 11, 19, 33, 50, 70, 90, 108, 123, 130, 114, 96, 77, 58, 43, 32, 25, 25, 32, 45, 85, 65, 51, 43, 42, 47, 58, 74, 94, 105, 81, 68, 62, 63, 70, 84, 103, 127, 154, 218, 193, 167, 142, 119, 101, 89, 83, 84, 96, 118, 104, 106, 116, 132, 152, 175, 198, 221, 241, 255, 248, 236, 219, 199, 178, 158, 140, 126, 121, 140, 157, 176, 195, 213, 227, 237, 241, 239, 193, 210, 221, 225, 222, 214, 201, 184, 164, 142, 160, 181, 196, 204, 206, 202, 191, 174, 152, 125 }; const uint8_t coordsY[NUM_PIXELS] { 130, 121, 105, 86, 66, 47, 31, 19, 13, 13, 55, 39, 30, 28, 33, 43, 57, 75, 95, 115, 96, 75, 60, 50, 46, 49, 59, 74, 96, 122, 166, 139, 114, 93, 78, 69, 67, 72, 85, 112, 102, 90, 89, 96, 110, 129, 152, 177, 203, 227, 247, 228, 207, 184, 161, 140, 123, 112, 109, 126, 132, 146, 165, 185, 206, 225, 240, 251, 255, 224, 235, 240, 237, 229, 216, 199, 181, 161, 143, 139, 166, 186, 202, 215, 221, 222, 216, 204, 185, 115, 142, 166, 184, 197, 203, 202, 195, 181, 158, 167, 180, 182, 178, 166, 148, 126, 101, 74, 21, 42, 66, 91, 114, 134, 150, 159, 160, 147, 141, 137, 124, 106, 85, 63, 42, 24, 9, 0 }; const uint8_t angles[NUM_PIXELS] { 0, 247, 239, 230, 221, 212, 203, 194, 186, 177, 154, 163, 171, 180, 189, 198, 207, 216, 224, 233, 210, 201, 192, 184, 175, 166, 157, 148, 139, 131, 116, 125, 134, 143, 152, 160, 169, 178, 187, 196, 173, 164, 155, 146, 137, 129, 120, 111, 102, 93, 79, 88, 97, 105, 114, 123, 132, 141, 150, 135, 126, 118, 109, 100, 91, 82, 73, 65, 56, 33, 42, 50, 59, 68, 77, 86, 95, 103, 112, 98, 89, 80, 71, 63, 54, 45, 36, 27, 18, 252, 4, 13, 22, 31, 39, 48, 57, 66, 75, 52, 43, 34, 25, 16, 8, 255, 246, 237, 214, 223, 232, 241, 250, 2, 11, 20, 29, 37, 14, 5, 253, 244, 235, 226, 218, 209, 200, 191 }; + static const auto (&radiusProxy)[NUM_PIXELS] = physicalToFibonacci; + static const uint8_t RADII_SCALE_DIVISOR { 1 }; + static const uint8_t RADII_SCALE_MULTIPLIER { 2 }; #elif defined(PRODUCT_FIBONACCI64_FULL) || defined(PRODUCT_FIBONACCI64_MINI) const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 39, 52, 57, 44, 31, 18, 5, 10, 23, 36, 49, 62, 54, 41, 28, 15, 2, 7, 20, 33, 46, 59, 51, 38, 25, 12, 4, 17, 30, 43, 56, 61, 48, 35, 22, 9, 1, 14, 27, 40, 53, 58, 45, 32, 19, 6, 11, 24, 37, 50, 63, 55, 42, 29, 16, 3, 8, 21, 34, 47, 60 }; const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 39, 19, 58, 29, 9, 48, 20, 59, 38, 10, 49, 28, 1, 40, 18, 57, 30, 8, 47, 21, 60, 37, 11, 50, 27, 2, 41, 17, 56, 31, 7, 46, 22, 61, 36, 12, 51, 26, 3, 42, 16, 55, 32, 6, 45, 23, 62, 35, 13, 52, 25, 4, 43, 15, 54, 33, 5, 44, 24, 63, 34, 14, 53 }; const uint8_t coordsX[NUM_PIXELS] { 140, 189, 208, 214, 208, 146, 168, 180, 180, 162, 152, 146, 129, 103, 72, 40, 70, 97, 120, 131, 107, 79, 50, 23, 0, 7, 23, 46, 76, 93, 57, 37, 28, 29, 87, 68, 59, 62, 80, 113, 91, 94, 109, 133, 202, 172, 145, 125, 117, 145, 170, 198, 227, 253, 255, 235, 210, 181, 148, 175, 207, 228, 240, 244 }; const uint8_t coordsY[NUM_PIXELS] { 128, 114, 91, 63, 34, 0, 21, 48, 76, 106, 78, 47, 25, 11, 5, 38, 35, 42, 61, 101, 87, 69, 68, 78, 98, 143, 118, 102, 98, 122, 131, 152, 179, 209, 255, 230, 202, 174, 148, 142, 181, 210, 235, 252, 235, 234, 224, 203, 170, 183, 201, 205, 198, 181, 134, 157, 171, 173, 153, 145, 138, 120, 93, 63 }; const uint8_t angles[NUM_PIXELS] { 0, 249, 241, 232, 223, 200, 208, 217, 226, 235, 212, 203, 194, 185, 176, 162, 171, 180, 188, 197, 174, 165, 156, 147, 139, 124, 133, 142, 151, 136, 128, 119, 110, 101, 78, 86, 95, 104, 113, 99, 90, 81, 72, 63, 40, 49, 58, 67, 75, 52, 43, 34, 25, 17, 2, 11, 20, 29, 38, 14, 6, 255, 246, 237 }; + static const auto (&radiusProxy)[NUM_PIXELS] = physicalToFibonacci; + static const uint8_t RADII_SCALE_DIVISOR { 1 }; + static const uint8_t RADII_SCALE_MULTIPLIER { 4 }; #elif defined(PRODUCT_FIBONACCI32) const uint8_t physicalToFibonacci[NUM_PIXELS] { 0, 13, 26, 31, 18, 5, 10, 23, 28, 15, 2, 7, 20, 33, 25, 12, 4, 17, 30, 22, 9, 1, 14, 27, 32, 19, 6, 11, 24, 29, 16, 3, 8, 21 }; const uint8_t fibonacciToPhysical[NUM_PIXELS] { 0, 21, 10, 31, 16, 5, 26, 11, 32, 20, 6, 27, 15, 1, 22, 9, 30, 17, 4, 25, 12, 33, 19, 7, 28, 14, 2, 23, 8, 29, 18, 3, 24, 13 }; @@ -87,6 +99,9 @@ const uint8_t angles[NUM_PIXELS] { 0, 249, 241, 232, 223, 200, 208, 217, 226, 235, 212, 203, 194, 185, 176, 162, 171, 180, 188, 197, 174, 165, 156, 147, 139, 124, 133, 142, 151, 136, 128, 119, 110, 101, 78, 86, 95, 104, 113, 99, 90, 81, 72, 63, 40, 49, 58, 67, 75, 52, 43, 34, 25, 17, 2, 11, 20, 29, 38, 14, 6, 255, 246, 237 }; const uint8_t body[NUM_PIXELS] { 0, 16, 32, 48, 64, 80, 96, 112, 128, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 255, 143, 159, 175, 191, 207, 223, 239, 255 }; static_assert(NUM_PIXELS == ARRAY_SIZE2(body), ""); + static const auto (&radiusProxy)[NUM_PIXELS] = body; + static const uint8_t RADII_SCALE_DIVISOR { 1 }; // body[] values are already in range [0..255] + static const uint8_t RADII_SCALE_MULTIPLIER { 1 }; // body[] values are already in range [0..255] // For reference purposes... // const uint8_t head[9] { 0, 1, 2, 3, 4, 5, 6, 7, 8 }; // const uint8_t tentacle0[8] { 9, 10, 11, 12, 13, 14, 15, 16 }; @@ -96,53 +111,87 @@ // const uint8_t tentacle4[8] { 40, 41, 42, 43, 44, 45, 46, 47 }; // const uint8_t tentacle5[8] { 48, 49, 50, 51, 52, 53, 54, 55 }; // const uint8_t tentacle6[8] { 56, 57, 58, 59, 60, 61, 62, 63 }; +#elif defined(PRODUCT_1628_RINGS) + // Yes, this is 1628 pixels ... all driven by one ESP8266 + // 20 concentric rings of pixel goodness! + const uint8_t coordsX[NUM_PIXELS] { 134, 128, 121, 128, 140, 139, 134, 128, 121, 116, 115, 116, 121, 128, 134, 139, 147, 146, 143, 139, 134, 129, 123, 118, 113, 110, 109, 109, 110, 113, 118, 123, 129, 134, 139, 143, 146, 153, 152, 151, 148, 144, 139, 134, 129, 123, 118, 113, 109, 106, 103, 102, 102, 103, 106, 109, 113, 118, 123, 129, 134, 139, 144, 148, 151, 152, 159, 159, 158, 155, 152, 149, 144, 139, 134, 129, 123, 118, 113, 109, 104, 101, 98, 97, 96, 96, 97, 98, 101, 104, 109, 113, 118, 123, 129, 134, 139, 144, 149, 152, 155, 158, 159, 166, 165, 164, 162, 160, 157, 153, 149, 144, 139, 134, 129, 124, 118, 113, 108, 104, 100, 97, 94, 92, 90, 89, 89, 90, 92, 94, 97, 100, 104, 108, 113, 118, 124, 129, 134, 139, 144, 149, 153, 157, 160, 162, 164, 165, 172, 172, 171, 169, 167, 165, 161, 158, 154, 149, 144, 139, 134, 129, 124, 118, 113, 108, 104, 99, 95, 92, 89, 87, 85, 84, 83, 83, 84, 85, 87, 89, 92, 95, 99, 104, 108, 113, 118, 124, 129, 134, 139, 144, 149, 154, 158, 161, 165, 167, 169, 171, 172, 179, 178, 177, 176, 174, 172, 169, 166, 163, 159, 154, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 101, 96, 92, 89, 86, 83, 81, 79, 78, 77, 77, 77, 78, 79, 81, 83, 86, 89, 92, 96, 101, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 154, 159, 163, 166, 169, 172, 174, 176, 177, 178, 185, 185, 184, 183, 181, 179, 177, 174, 171, 167, 163, 159, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 96, 92, 88, 84, 81, 78, 76, 74, 72, 71, 70, 70, 70, 71, 72, 74, 76, 78, 81, 84, 88, 92, 96, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 159, 163, 167, 171, 174, 177, 179, 181, 183, 184, 185, 191, 191, 190, 189, 188, 186, 184, 181, 178, 175, 172, 168, 164, 159, 155, 150, 145, 140, + 135, 130, 125, 120, 115, 110, 105, 100, 96, 91, 87, 83, 80, 77, 74, 71, 69, 67, 66, 65, 64, 64, 64, 65, 66, 67, 69, 71, 74, 77, 80, 83, 87, 91, 96, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 159, 164, 168, 172, 175, 178, 181, 184, 186, 188, 189, 190, 191, 198, 197, 197, 196, 195, 193, 191, 189, 186, 183, 180, 176, 172, 168, 164, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 91, 87, 83, 79, 75, 72, 69, 66, 64, 62, 60, 59, 58, 58, 57, 58, 58, 59, 60, 62, 64, 66, 69, 72, 75, 79, 83, 87, 91, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 164, 168, 172, 176, 180, 183, 186, 189, 191, 193, 195, 196, 197, 197, 204, 204, 203, 202, 201, 200, 198, 196, 193, 191, 188, 184, 181, 177, 173, 169, 164, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 91, 86, 82, 78, 74, 71, 67, 64, 62, 59, 57, 55, 54, 53, 52, 51, 51, 51, 52, 53, 54, 55, 57, 59, 62, 64, 67, 71, 74, 78, 82, 86, 91, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 164, 169, 173, 177, 181, 184, 188, 191, 193, 196, 198, 200, 201, 202, 203, 204, 210, 210, 210, 209, 208, 206, 205, 203, 201, 198, 195, 192, 189, 185, 181, 177, 173, 169, 164, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 91, 86, 82, 78, 74, 70, 66, 63, 60, 57, 54, 52, 50, 49, 47, 46, 45, 45, 45, 45, 45, 46, 47, 49, 50, 52, 54, 57, 60, 63, 66, 70, 74, 78, 82, 86, 91, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 164, 169, 173, 177, 181, 185, 189, 192, 195, 198, 201, 203, 205, 206, 208, 209, 210, 210, 217, 217, 216, 215, 214, 213, 212, 210, 208, 205, 203, 200, 197, 193, 190, 186, 182, 178, 174, + 169, 165, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 90, 86, 81, 77, 73, 69, 65, 62, 58, 55, 52, 50, 47, 45, 43, 42, 41, 40, 39, 38, 38, 38, 39, 40, 41, 42, 43, 45, 47, 50, 52, 55, 58, 62, 65, 69, 73, 77, 81, 86, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 169, 174, 178, 182, 186, 190, 193, 197, 200, 203, 205, 208, 210, 212, 213, 214, 215, 216, 217, 223, 223, 223, 222, 221, 220, 218, 217, 215, 212, 210, 207, 204, 201, 198, 194, 190, 187, 182, 178, 174, 169, 165, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 90, 86, 81, 77, 73, 68, 65, 61, 57, 54, 51, 48, 45, 43, 40, 38, 37, 35, 34, 33, 32, 32, 32, 32, 32, 33, 34, 35, 37, 38, 40, 43, 45, 48, 51, 54, 57, 61, 65, 68, 73, 77, 81, 86, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 169, 174, 178, 182, 187, 190, 194, 198, 201, 204, 207, 210, 212, 215, 217, 218, 220, 221, 222, 223, 223, 230, 229, 229, 228, 227, 226, 225, 223, 221, 219, 217, 214, 212, 208, 205, 202, 198, 194, 191, 186, 182, 178, 173, 169, 164, 159, 154, 149, 144, 139, 134, 129, 124, 119, 113, 108, 103, 98, 94, 89, 84, 79, 75, 71, 67, 62, 59, 55, 51, 48, 45, 42, 39, 37, 35, 33, 31, 29, 28, 27, 26, 26, 26, 26, 26, 26, 27, 28, 29, 31, 33, 35, 37, 39, 42, 45, 48, 51, 55, 59, 62, 67, 71, 75, 79, 84, 89, 94, 98, 103, 108, 113, 119, 124, 129, 134, 139, 144, 149, 154, 159, 164, 169, 173, 178, 182, 186, 191, 194, 198, 202, 205, 208, 212, 214, 217, 219, 221, 223, 225, 226, 227, 228, 229, 229, 236, 236, 235, 235, 234, 233, 232, 230, 228, 227, 224, 222, 219, 217, 214, 211, 207, 204, 200, 196, 192, 188, 184, 179, 175, 170, 166, 161, 156, 151, + 146, 141, 136, 131, 126, 121, 116, 111, 106, 101, 96, 92, 87, 82, 78, 73, 69, 65, 61, 57, 53, 50, 46, 43, 40, 37, 34, 32, 30, 27, 26, 24, 23, 21, 21, 20, 19, 19, 19, 19, 20, 21, 21, 23, 24, 26, 27, 30, 32, 34, 37, 40, 43, 46, 50, 53, 57, 61, 65, 69, 73, 78, 82, 87, 92, 96, 101, 106, 111, 116, 121, 126, 131, 136, 141, 146, 151, 156, 161, 166, 170, 175, 179, 184, 188, 192, 196, 200, 204, 207, 211, 214, 217, 219, 222, 224, 227, 228, 230, 232, 233, 234, 235, 235, 236, 242, 242, 242, 241, 240, 239, 238, 237, 235, 233, 231, 229, 226, 224, 221, 218, 215, 211, 208, 204, 200, 196, 192, 188, 183, 179, 174, 170, 165, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 90, 85, 81, 76, 72, 67, 63, 59, 55, 51, 47, 44, 40, 37, 34, 31, 29, 26, 24, 22, 20, 18, 17, 16, 15, 14, 13, 13, 13, 13, 13, 14, 15, 16, 17, 18, 20, 22, 24, 26, 29, 31, 34, 37, 40, 44, 47, 51, 55, 59, 63, 67, 72, 76, 81, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 174, 179, 183, 188, 192, 196, 200, 204, 208, 211, 215, 218, 221, 224, 226, 229, 231, 233, 235, 237, 238, 239, 240, 241, 242, 242, 249, 249, 248, 248, 247, 246, 245, 243, 241, 240, 237, 235, 233, 230, 227, 224, 221, 217, 214, 210, 206, 202, 198, 193, 189, 184, 180, 175, 170, 165, 160, 155, 150, 145, 139, 134, 129, 124, 118, 113, 108, 103, 98, 93, 88, 83, 78, 73, 68, 64, 60, 55, 51, 47, 43, 40, 36, 33, 30, 27, 24, 21, 19, 16, 14, 13, 11, 10, 9, 8, 7, 7, 6, 6, 7, 7, 8, 9, 10, 11, 13, 14, 16, 19, 21, 24, 27, 30, 33, 36, 40, 43, 47, 51, 55, 60, 64, 68, 73, 78, 83, 88, 93, 98, 103, 108, 113, 118, 124, 129, 134, 139, 145, 150, 155, 160, 165, 170, 175, 180, 184, 189, 193, 198, 202, 206, + 210, 214, 217, 221, 224, 227, 230, 233, 235, 237, 240, 241, 243, 245, 246, 247, 248, 248, 249, 255, 255, 255, 254, 253, 253, 251, 250, 249, 247, 245, 243, 241, 239, 236, 234, 231, 228, 224, 221, 218, 214, 210, 206, 202, 198, 194, 190, 185, 181, 176, 172, 167, 162, 157, 152, 147, 142, 138, 133, 128, 122, 117, 113, 108, 103, 98, 93, 88, 83, 79, 74, 70, 65, 61, 57, 53, 49, 45, 41, 37, 34, 31, 27, 24, 21, 19, 16, 14, 12, 10, 8, 6, 5, 4, 2, 2, 1, 0, 0, 0, 0, 0, 1, 2, 2, 4, 5, 6, 8, 10, 12, 14, 16, 19, 21, 24, 27, 31, 34, 37, 41, 45, 49, 53, 57, 61, 65, 70, 74, 79, 83, 88, 93, 98, 103, 108, 113, 117, 122, 127, 133, 138, 142, 147, 152, 157, 162, 167, 172, 176, 181, 185, 190, 194, 198, 202, 206, 210, 214, 218, 221, 224, 228, 231, 234, 236, 239, 241, 243, 245, 247, 249, 250, 251, 253, 253, 254, 255, 255 }; + const uint8_t coordsY[NUM_PIXELS] { 128, 134, 128, 121, 128, 134, 139, 140, 139, 134, 128, 121, 116, 115, 116, 121, 128, 133, 138, 142, 145, 147, 146, 144, 141, 136, 130, 125, 119, 114, 111, 109, 108, 110, 113, 117, 122, 128, 133, 138, 143, 147, 150, 152, 153, 153, 151, 149, 145, 141, 136, 130, 125, 119, 114, 110, 106, 104, 102, 102, 103, 105, 108, 112, 117, 122, 128, 133, 138, 143, 148, 151, 155, 157, 159, 159, 159, 158, 156, 153, 150, 145, 141, 136, 130, 125, 119, 114, 110, 105, 102, 99, 97, 96, 96, 96, 98, 100, 104, 107, 112, 117, 122, 128, 133, 138, 143, 148, 152, 156, 159, 162, 164, 165, 166, 166, 165, 163, 161, 158, 154, 150, 145, 141, 135, 130, 125, 120, 114, 110, 105, 101, 97, 94, 92, 90, 89, 89, 90, 91, 93, 96, 99, 103, 107, 112, 117, 122, 128, 133, 138, 143, 148, 152, 157, 160, 164, 167, 169, 171, 172, 172, 172, 171, 170, 168, 165, 162, 159, 155, 150, 145, 141, 135, 130, 125, 120, 114, 110, 105, 100, 96, 93, 90, 87, 85, 84, 83, 83, 83, 84, 86, 88, 91, 95, 98, 103, 107, 112, 117, 122, 128, 133, 138, 143, 148, 152, 157, 161, 164, 168, 171, 173, 175, 177, 178, 178, 178, 178, 177, 175, 173, 171, 168, 164, 161, 157, 152, 148, 143, 138, 133, 128, 122, 117, 112, 107, 103, 98, 94, 91, 87, 84, 82, 80, 78, 77, 77, 77, 77, 78, 80, 82, 84, 87, 91, 94, 98, 103, 107, 112, 117, 122, 128, 133, 138, 143, 148, 152, 157, 161, 165, 169, 172, 175, 178, 180, 182, 183, 184, 185, 185, 184, 183, 182, 180, 178, 175, 172, 169, 165, 161, 157, 152, 148, 143, 138, 133, 128, 122, 117, 112, 107, 103, 98, 94, 90, 86, 83, 80, 77, 75, 73, 72, 71, 70, 70, 71, 72, 73, 75, 77, 80, 83, 86, 90, 94, 98, 103, 107, 112, 117, 122, 128, 133, 138, 143, 148, 152, 157, 162, 166, 170, 173, 177, 180, 183, 185, 187, 189, 190, + 191, 191, 191, 191, 190, 189, 187, 185, 183, 180, 177, 173, 170, 166, 162, 157, 152, 148, 143, 138, 133, 128, 122, 117, 112, 107, 103, 98, 93, 89, 85, 82, 78, 75, 72, 70, 68, 66, 65, 64, 64, 64, 64, 65, 66, 68, 70, 72, 75, 78, 82, 85, 89, 93, 98, 103, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 157, 162, 166, 170, 174, 178, 181, 185, 187, 190, 192, 194, 195, 196, 197, 198, 198, 197, 196, 195, 194, 192, 190, 187, 185, 181, 178, 174, 170, 166, 162, 157, 153, 148, 143, 138, 133, 128, 122, 117, 112, 107, 102, 98, 93, 89, 85, 81, 77, 74, 70, 68, 65, 63, 61, 60, 59, 58, 57, 57, 58, 59, 60, 61, 63, 65, 68, 70, 74, 77, 81, 85, 89, 93, 98, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 157, 162, 166, 171, 175, 179, 182, 186, 189, 192, 195, 197, 199, 201, 202, 203, 204, 204, 204, 204, 203, 202, 201, 199, 197, 195, 192, 189, 186, 182, 179, 175, 171, 166, 162, 157, 153, 148, 143, 138, 133, 128, 122, 117, 112, 107, 102, 98, 93, 89, 84, 80, 76, 73, 69, 66, 63, 60, 58, 56, 54, 53, 52, 51, 51, 51, 51, 52, 53, 54, 56, 58, 60, 63, 66, 69, 73, 76, 80, 84, 89, 93, 98, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 157, 162, 167, 171, 175, 179, 183, 187, 190, 194, 197, 199, 202, 204, 206, 207, 208, 209, 210, 210, 210, 210, 209, 208, 207, 206, 204, 202, 199, 197, 194, 190, 187, 183, 179, 175, 171, 167, 162, 157, 153, 148, 143, 138, 133, 128, 122, 117, 112, 107, 102, 98, 93, 88, 84, 80, 76, 72, 68, 65, 61, 58, 56, 53, 51, 49, 48, 47, 46, 45, 45, 45, 45, 46, 47, 48, 49, 51, 53, 56, 58, 61, 65, 68, 72, 76, 80, 84, 88, 93, 98, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 157, 162, 167, 171, 176, 180, 184, 188, 192, 195, 198, 201, 204, 206, 209, + 211, 212, 214, 215, 216, 216, 217, 217, 216, 216, 215, 214, 212, 211, 209, 206, 204, 201, 198, 195, 192, 188, 184, 180, 176, 171, 167, 162, 157, 153, 148, 143, 138, 133, 128, 122, 117, 112, 107, 102, 98, 93, 88, 84, 79, 75, 71, 67, 63, 60, 57, 54, 51, 49, 46, 44, 43, 41, 40, 39, 39, 38, 38, 39, 39, 40, 41, 43, 44, 46, 49, 51, 54, 57, 60, 63, 67, 71, 75, 79, 84, 88, 93, 98, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 158, 162, 167, 172, 176, 180, 185, 189, 192, 196, 199, 203, 206, 209, 211, 213, 216, 217, 219, 220, 221, 222, 223, 223, 223, 223, 222, 221, 220, 219, 217, 216, 213, 211, 209, 206, 203, 199, 196, 192, 189, 185, 180, 176, 172, 167, 162, 158, 153, 148, 143, 138, 133, 128, 122, 117, 112, 107, 102, 97, 93, 88, 83, 79, 75, 70, 66, 63, 59, 56, 52, 49, 46, 44, 42, 39, 38, 36, 35, 34, 33, 32, 32, 32, 32, 33, 34, 35, 36, 38, 39, 42, 44, 46, 49, 52, 56, 59, 63, 66, 70, 75, 79, 83, 88, 93, 97, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 158, 163, 167, 172, 177, 181, 185, 190, 193, 197, 201, 204, 208, 211, 214, 216, 219, 221, 223, 225, 226, 227, 228, 229, 229, 229, 229, 229, 229, 228, 227, 225, 224, 222, 220, 217, 215, 212, 209, 206, 203, 199, 195, 192, 187, 183, 179, 174, 170, 165, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 90, 85, 81, 76, 72, 68, 63, 60, 56, 52, 49, 46, 43, 40, 38, 35, 33, 31, 30, 28, 27, 26, 26, 26, 26, 26, 26, 27, 28, 29, 30, 32, 34, 36, 39, 41, 44, 47, 51, 54, 58, 62, 65, 70, 74, 78, 83, 88, 92, 97, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 152, 157, 162, 167, 172, 176, 181, 185, 189, 193, 197, 201, 205, 208, 211, 214, 217, 220, 223, 225, 227, 229, 231, 232, 233, 234, 235, 236, + 236, 236, 236, 235, 235, 234, 233, 231, 230, 228, 226, 224, 221, 219, 216, 213, 210, 206, 203, 199, 195, 191, 187, 183, 178, 174, 169, 165, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 90, 86, 81, 77, 72, 68, 64, 60, 56, 52, 49, 45, 42, 39, 36, 34, 31, 29, 27, 25, 24, 22, 21, 20, 20, 19, 19, 19, 19, 20, 21, 22, 23, 24, 26, 28, 30, 32, 35, 38, 41, 44, 47, 50, 54, 58, 62, 66, 70, 74, 79, 83, 88, 93, 98, 103, 107, 112, 117, 122, 128, 133, 138, 143, 148, 153, 158, 162, 167, 172, 177, 181, 186, 190, 194, 198, 202, 206, 210, 213, 216, 219, 222, 225, 228, 230, 232, 234, 236, 238, 239, 240, 241, 242, 242, 242, 242, 242, 242, 241, 240, 239, 238, 236, 234, 232, 230, 228, 225, 222, 219, 216, 213, 210, 206, 202, 198, 194, 190, 186, 181, 177, 172, 167, 162, 158, 153, 148, 143, 138, 133, 128, 122, 117, 112, 107, 102, 97, 93, 88, 83, 78, 74, 69, 65, 61, 57, 53, 49, 45, 42, 39, 36, 33, 30, 27, 25, 23, 21, 19, 17, 16, 15, 14, 13, 13, 13, 13, 13, 13, 14, 15, 16, 17, 19, 21, 23, 25, 27, 30, 33, 36, 39, 42, 45, 49, 53, 57, 61, 65, 69, 74, 78, 83, 88, 93, 97, 102, 107, 112, 117, 122, 128, 133, 138, 143, 148, 154, 159, 164, 169, 174, 178, 183, 188, 192, 197, 201, 205, 209, 213, 216, 220, 223, 226, 229, 232, 235, 237, 239, 241, 243, 244, 246, 247, 247, 248, 248, 249, 249, 248, 248, 247, 246, 245, 243, 242, 240, 238, 236, 233, 231, 228, 225, 221, 218, 215, 211, 207, 203, 199, 194, 190, 185, 181, 176, 171, 166, 161, 156, 151, 146, 141, 135, 130, 125, 120, 114, 109, 104, 99, 94, 89, 84, 79, 74, 70, 65, 61, 56, 52, 48, 44, 40, 37, 34, 30, 27, 24, 22, 19, 17, 15, 13, 12, 10, 9, 8, 7, 7, 6, 6, 7, 7, 8, 8, 9, 11, 12, 14, 16, 18, 20, 23, 26, 29, 32, 35, + 39, 42, 46, 50, 54, 58, 63, 67, 72, 77, 81, 86, 91, 96, 101, 107, 112, 117, 122, 128, 133, 138, 142, 147, 152, 157, 162, 167, 172, 176, 181, 185, 190, 194, 198, 202, 206, 210, 214, 218, 221, 224, 228, 231, 234, 236, 239, 241, 243, 245, 247, 249, 250, 251, 253, 253, 254, 255, 255, 255, 255, 255, 254, 253, 253, 251, 250, 249, 247, 245, 243, 241, 239, 236, 234, 231, 228, 224, 221, 218, 214, 210, 206, 202, 198, 194, 190, 185, 181, 176, 172, 167, 162, 157, 152, 147, 142, 138, 133, 128, 122, 117, 113, 108, 103, 98, 93, 88, 83, 79, 74, 70, 65, 61, 57, 53, 49, 45, 41, 37, 34, 31, 27, 24, 21, 19, 16, 14, 12, 10, 8, 6, 5, 4, 2, 2, 1, 0, 0, 0, 0, 0, 1, 2, 2, 4, 5, 6, 8, 10, 12, 14, 16, 19, 21, 24, 27, 31, 34, 37, 41, 45, 49, 53, 57, 61, 65, 70, 74, 79, 83, 88, 93, 98, 103, 108, 113, 117, 122 }; + const uint8_t angles[NUM_PIXELS] { 0, 64, 128, 191, 0, 21, 43, 64, 85, 106, 128, 149, 170, 191, 213, 234, 0, 12, 24, 36, 49, 61, 73, 85, 97, 109, 121, 134, 146, 158, 170, 182, 194, 206, 219, 231, 243, 0, 9, 18, 26, 35, 44, 53, 62, 70, 79, 88, 97, 106, 114, 123, 132, 141, 149, 158, 167, 176, 185, 193, 202, 211, 220, 229, 237, 246, 0, 7, 14, 21, 28, 34, 41, 48, 55, 62, 69, 76, 83, 90, 96, 103, 110, 117, 124, 131, 138, 145, 152, 159, 165, 172, 179, 186, 193, 200, 207, 214, 221, 227, 234, 241, 248, 0, 6, 11, 17, 23, 28, 34, 40, 45, 51, 57, 62, 68, 74, 79, 85, 91, 96, 102, 108, 113, 119, 125, 130, 136, 142, 147, 153, 159, 164, 170, 176, 181, 187, 193, 198, 204, 210, 215, 221, 227, 232, 238, 244, 249, 0, 5, 10, 14, 19, 24, 29, 34, 38, 43, 48, 53, 58, 63, 67, 72, 77, 82, 87, 91, 96, 101, 106, 111, 115, 120, 125, 130, 135, 140, 144, 149, 154, 159, 164, 168, 173, 178, 183, 188, 192, 197, 202, 207, 212, 217, 221, 226, 231, 236, 241, 245, 250, 0, 4, 8, 12, 16, 21, 25, 29, 33, 37, 41, 45, 49, 53, 58, 62, 66, 70, 74, 78, 82, 86, 90, 95, 99, 103, 107, 111, 115, 119, 123, 128, 132, 136, 140, 144, 148, 152, 156, 160, 165, 169, 173, 177, 181, 185, 189, 193, 197, 202, 206, 210, 214, 218, 222, 226, 230, 234, 239, 243, 247, 251, 0, 4, 7, 11, 15, 18, 22, 26, 29, 33, 36, 40, 44, 47, 51, 55, 58, 62, 66, 69, 73, 77, 80, 84, 87, 91, 95, 98, 102, 106, 109, 113, 117, 120, 124, 128, 131, 135, 138, 142, 146, 149, 153, 157, 160, 164, 168, 171, 175, 179, 182, 186, 189, 193, 197, 200, 204, 208, 211, 215, 219, 222, 226, 230, 233, 237, 240, 244, 248, 251, 0, 3, 7, 10, 13, 16, 20, 23, 26, 29, 33, 36, 39, 43, 46, 49, 52, 56, 59, 62, 65, 69, 72, 75, 78, 82, 85, 88, 92, 95, 98, 101, 105, 108, 111, 114, 118, 121, 124, 127, + 131, 134, 137, 141, 144, 147, 150, 154, 157, 160, 163, 167, 170, 173, 177, 180, 183, 186, 190, 193, 196, 199, 203, 206, 209, 213, 216, 219, 222, 226, 229, 232, 235, 239, 242, 245, 248, 252, 0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 92, 95, 98, 101, 104, 107, 110, 113, 116, 119, 122, 125, 128, 130, 133, 136, 139, 142, 145, 148, 151, 154, 157, 160, 163, 166, 169, 172, 175, 178, 181, 184, 187, 190, 193, 196, 199, 202, 205, 208, 211, 213, 216, 219, 222, 225, 228, 231, 234, 237, 240, 243, 246, 249, 252, 0, 3, 5, 8, 11, 14, 16, 19, 22, 24, 27, 30, 33, 35, 38, 41, 43, 46, 49, 52, 54, 57, 60, 62, 65, 68, 71, 73, 76, 79, 81, 84, 87, 90, 92, 95, 98, 100, 103, 106, 109, 111, 114, 117, 119, 122, 125, 128, 130, 133, 136, 138, 141, 144, 146, 149, 152, 155, 157, 160, 163, 165, 168, 171, 174, 176, 179, 182, 184, 187, 190, 193, 195, 198, 201, 203, 206, 209, 212, 214, 217, 220, 222, 225, 228, 231, 233, 236, 239, 241, 244, 247, 250, 252, 0, 3, 5, 8, 10, 13, 15, 17, 20, 23, 25, 27, 30, 33, 35, 37, 40, 43, 45, 48, 50, 53, 55, 57, 60, 63, 65, 68, 70, 73, 75, 78, 80, 83, 85, 88, 90, 93, 95, 98, 100, 102, 105, 107, 110, 113, 115, 118, 120, 123, 125, 128, 130, 133, 135, 138, 140, 142, 145, 147, 150, 153, 155, 158, 160, 163, 165, 168, 170, 173, 175, 178, 180, 182, 185, 187, 190, 193, 195, 198, 200, 203, 205, 208, 210, 213, 215, 218, 220, 223, 225, 228, 230, 233, 235, 238, 240, 243, 245, 247, 250, 252, 0, 2, 5, 7, 9, 12, 14, 16, 19, 21, 23, 26, 28, 30, 32, 35, 37, 39, 42, 44, 46, 49, 51, 53, 56, 58, 60, 63, 65, 67, 70, 72, 74, 77, 79, 81, 83, 86, 88, 90, 93, 95, 97, 100, 102, 104, 107, 109, 111, 114, + 116, 118, 121, 123, 125, 128, 130, 132, 134, 137, 139, 141, 144, 146, 148, 151, 153, 155, 158, 160, 162, 165, 167, 169, 172, 174, 176, 179, 181, 183, 185, 188, 190, 192, 195, 197, 199, 202, 204, 206, 209, 211, 213, 216, 218, 220, 223, 225, 227, 230, 232, 234, 236, 239, 241, 243, 246, 248, 250, 253, 0, 2, 4, 6, 9, 11, 13, 15, 17, 19, 22, 24, 26, 28, 30, 32, 35, 37, 39, 41, 43, 45, 48, 50, 52, 54, 56, 58, 61, 63, 65, 67, 69, 71, 73, 76, 78, 80, 82, 84, 86, 89, 91, 93, 95, 97, 99, 102, 104, 106, 108, 110, 112, 115, 117, 119, 121, 123, 125, 128, 130, 132, 134, 136, 138, 140, 143, 145, 147, 149, 151, 153, 156, 158, 160, 162, 164, 166, 169, 171, 173, 175, 177, 179, 182, 184, 186, 188, 190, 192, 194, 197, 199, 201, 203, 205, 207, 210, 212, 214, 216, 218, 220, 223, 225, 227, 229, 231, 233, 236, 238, 240, 242, 244, 246, 249, 251, 253, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 129, 131, 133, 135, 137, 139, 141, 143, 145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173, 175, 177, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 0, 2, 4, 6, 8, 9, 11, 13, 15, 17, 19, 21, 23, 25, 26, 28, 30, 32, 34, 36, 38, 40, 42, 43, 45, 47, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66, 68, 70, 72, 74, 76, 77, 79, 81, 83, 85, 87, 89, 91, 93, 94, 96, 98, 100, 102, 104, 106, 108, 110, 111, 113, 115, 117, 119, 121, 123, + 125, 127, 128, 130, 132, 134, 136, 138, 140, 142, 144, 145, 147, 149, 151, 153, 155, 157, 159, 161, 162, 164, 166, 168, 170, 172, 174, 176, 178, 179, 181, 183, 185, 187, 189, 191, 193, 195, 196, 198, 200, 202, 204, 206, 208, 210, 212, 213, 215, 217, 219, 221, 223, 225, 227, 229, 230, 232, 234, 236, 238, 240, 242, 244, 246, 247, 249, 251, 253, 0, 2, 4, 5, 7, 9, 11, 13, 14, 16, 18, 20, 22, 23, 25, 27, 29, 31, 32, 34, 36, 38, 40, 41, 43, 45, 47, 48, 50, 52, 54, 56, 57, 59, 61, 63, 65, 66, 68, 70, 72, 74, 75, 77, 79, 81, 83, 84, 86, 88, 90, 92, 93, 95, 97, 99, 101, 102, 104, 106, 108, 110, 111, 113, 115, 117, 119, 120, 122, 124, 126, 128, 129, 131, 133, 135, 136, 138, 140, 142, 144, 145, 147, 149, 151, 153, 154, 156, 158, 160, 162, 163, 165, 167, 169, 171, 172, 174, 176, 178, 180, 181, 183, 185, 187, 189, 190, 192, 194, 196, 198, 199, 201, 203, 205, 207, 208, 210, 212, 214, 215, 217, 219, 221, 223, 224, 226, 228, 230, 232, 233, 235, 237, 239, 241, 242, 244, 246, 248, 250, 251, 253, 0, 2, 4, 5, 7, 9, 11, 12, 14, 16, 18, 19, 21, 23, 25, 26, 28, 30, 32, 33, 35, 37, 39, 40, 42, 44, 46, 47, 49, 51, 53, 55, 56, 58, 60, 62, 63, 65, 67, 69, 70, 72, 74, 76, 77, 79, 81, 83, 84, 86, 88, 90, 91, 93, 95, 97, 98, 100, 102, 104, 106, 107, 109, 111, 113, 114, 116, 118, 120, 121, 123, 125, 127, 128, 130, 132, 134, 135, 137, 139, 141, 142, 144, 146, 148, 149, 151, 153, 155, 157, 158, 160, 162, 164, 165, 167, 169, 171, 172, 174, 176, 178, 179, 181, 183, 185, 186, 188, 190, 192, 193, 195, 197, 199, 200, 202, 204, 206, 208, 209, 211, 213, 215, 216, 218, 220, 222, 223, 225, 227, 229, 230, 232, 234, 236, 237, 239, 241, 243, 244, 246, 248, 250, 251, 253, 0, 2, 3, 5, 6, 8, 10, + 11, 13, 14, 16, 18, 19, 21, 22, 24, 26, 27, 29, 30, 32, 33, 35, 37, 38, 40, 41, 43, 45, 46, 48, 49, 51, 53, 54, 56, 57, 59, 61, 62, 64, 65, 67, 69, 70, 72, 73, 75, 77, 78, 80, 81, 83, 84, 86, 88, 89, 91, 92, 94, 96, 97, 99, 100, 102, 104, 105, 107, 108, 110, 112, 113, 115, 116, 118, 120, 121, 123, 124, 126, 128, 129, 131, 132, 134, 135, 137, 139, 140, 142, 143, 145, 147, 148, 150, 151, 153, 155, 156, 158, 159, 161, 163, 164, 166, 167, 169, 171, 172, 174, 175, 177, 179, 180, 182, 183, 185, 186, 188, 190, 191, 193, 194, 196, 198, 199, 201, 202, 204, 206, 207, 209, 210, 212, 214, 215, 217, 218, 220, 222, 223, 225, 226, 228, 230, 231, 233, 234, 236, 237, 239, 241, 242, 244, 245, 247, 249, 250, 252, 253 }; + const uint8_t radii[NUM_PIXELS] { 13, 13, 13, 13, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 115, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, + 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, + 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 204, 217, 217, + 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 230, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, + 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 }; + static const auto (&radiusProxy)[NUM_PIXELS] = radii; + static const uint8_t RADII_SCALE_DIVISOR { 1 }; // radii[] values are already in range [0..255] + static const uint8_t RADII_SCALE_MULTIPLIER { 1 }; // radii[] values are already in range [0..255] + + // Polar coordinate mapping code for FastLED by Adam Haile, Maniacal Labs: + // http://maniacallabs.com/2015/05/04/review-code-adafruit-dotstar-disk/ + // https://gist.github.com/adammhaile/a769f3ff87ff61f22ace + + #define ringCount 20 // Total Number of Rings. AdaFruit Disk has 10 + #define lastRing (ringCount-1) // for convenience + + //Map rings on disk to indicies. + //Each represents one of the concentric rings. + //TODO: change to structure with min/max (inclusive), to clarify meaning of indices + const uint16_t rings[ringCount][2] { + // { first pixel of the ring, last pixel of the ring } // INCLUSIVE indices + { 0, 3 }, + { 4, 15 }, + { 16, 36 }, + { 37, 65 }, + { 66, 102 }, + { 103, 147 }, + { 148, 200 }, + { 201, 262 }, + { 263, 332 }, + { 333, 410 }, + { 411, 496 }, + { 497, 590 }, + { 591, 692 }, + { 693, 803 }, + { 804, 920 }, + { 921, 1045 }, + { 1046, 1180 }, + { 1181, 1322 }, + { 1323, 1467 }, + { 1468, 1627 }, + }; + + #else - #error "Unknown / Unsupported fibonacci product ... no mappings defined" + #error "Unknown / Unsupported product ... no mappings defined" #endif #if IS_FIBONACCI static_assert(NUM_PIXELS == ARRAY_SIZE2(physicalToFibonacci), ""); static_assert(NUM_PIXELS == ARRAY_SIZE2(fibonacciToPhysical), ""); #endif -#if HAS_COORDINATE_MAP - static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsX), ""); - static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsY), ""); - static_assert(NUM_PIXELS == ARRAY_SIZE2(angles), ""); -#endif // What is HAS_RADIUS_PROXY? It could be the actual radius, or it could be something // that is used "in place of" the radius during effects processing. // Use reference to original array; avoids repeating preprocessor checks throughout the code.... -#if defined(PRODUCT_KRAKEN64) - #define HAS_RADIUS_PROXY 1 - static const auto (&radiusProxy)[NUM_PIXELS] = body; - static const uint8_t RADII_SCALE_DIVISOR { 1 }; // body[] values are already in range [0..255] - static const uint8_t RADII_SCALE_MULTIPLIER { 1 }; // body[] values are already in range [0..255] -#elif IS_FIBONACCI - #define HAS_RADIUS_PROXY 1 - - static const auto (&radiusProxy)[NUM_PIXELS] = physicalToFibonacci; - - static_assert( - ((NUM_PIXELS & (NUM_PIXELS-1)) == 0) || - (NUM_PIXELS == 34), - "RADII_SCALE_MULTIPLIER / RADII_SCALE_DIVISOR need updates to handle other non-power-of-two NUM_PIXELS" - ); - static const uint8_t RADII_SCALE_DIVISOR { (NUM_PIXELS <= 256u) ? 1 : (NUM_PIXELS / 256u) }; - static const uint8_t RADII_SCALE_MULTIPLIER { - (NUM_PIXELS >= 256) ? 1 : - (NUM_PIXELS == 34) ? 8 : // Careful .. use saturating multiplier or manually limit to 256... - ((NUM_PIXELS & (NUM_PIXELS-1)) == 0) ? (256u/NUM_PIXELS) : - 0 - }; - static_assert(RADII_SCALE_MULTIPLIER != 0, ""); -#else - #define HAS_RADIUS_PROXY 0 // default is that this is not supported.... -#endif - -#if HAS_RADIUS_PROXY - static_assert(HAS_COORDINATE_MAP, "HAS_RADIUS_PROXY also requires coordinate map"); -#endif +static_assert(RADII_SCALE_DIVISOR >= 1, ""); +static_assert(RADII_SCALE_MULTIPLIER >= 1, ""); +#define HAS_RADIUS_PROXY 1 // functions below wrapped by this ... leave defined for now +static_assert(HAS_COORDINATE_MAP, ""); +static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsX), ""); +static_assert(NUM_PIXELS == ARRAY_SIZE2(coordsY), ""); +static_assert(NUM_PIXELS == ARRAY_SIZE2(angles), ""); #if IS_FIBONACCI // drawSpiralLine() uses angles[] and physicalToFibonacci[] void drawSpiralLine(uint8_t angle, int step, CRGB color) @@ -274,7 +323,6 @@ void anglePalette() { } #endif -// TODO - consider adding pre-computed radii[], enabled anytime HAS_COORDINATE_MAP is true #if HAS_RADIUS_PROXY // radiusPalette() uses radiusProxy[] void radiusPalette() { uint16_t hues = 1; @@ -422,7 +470,7 @@ void drawAnalogClock() { } #endif -// TODO: `drawSpiralAnalogClock13_21_and_34()` -- config to disable the seconds hand? +// TODO: `drawSpiralAnalogClock***()` -- config to disable the seconds hand? #if IS_FIBONACCI // drawSpiralAnalogClock*() calls drawSpiralLine(), which requires fibonacci void drawSpiralAnalogClock(uint8_t step_h, uint8_t step_m, uint8_t step_s) { @@ -486,5 +534,25 @@ void drawSpiralAnalogClock34_21_and_13() { } #endif +#if HAS_COORDINATE_MAP // radarSweepPalette() uses angles[] +void radarSweepPalette() { + fadeToBlackBy(leds, NUM_PIXELS, 64); + + uint8_t a = beat8(speed); + uint8_t b = beat88(1); + + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint8_t angle = angles[i]; + + if(abs(angle - a) < 3) { + leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed)); + } + if(abs(angle - b) < 3) { + leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) + 85); + } + } +} +#endif + #endif // IS_FIBONACCI || HAS_COORDINATE_MAP diff --git a/esp8266-fastled-webserver/Noise.h b/esp8266-fastled-webserver/Noise.h index 0f568d14..2457ddbc 100644 --- a/esp8266-fastled-webserver/Noise.h +++ b/esp8266-fastled-webserver/Noise.h @@ -69,8 +69,21 @@ static const CRGBPalette16 blackAndBlueStripedPalette { // Additionally, you can manually define your own color palettes, or you can write // code that creates color palettes on the fly. -// TODO: Is Fib512 have a bug, because it uses `uint8_t` as data type for loop index, -// which will never be >= 512, and thus loop infinitely? +CRGB noiseXYZ(CRGBPalette16 palette, uint8_t hueReduce, int x, int y, int z) +{ + uint8_t data = inoise8(x, y, z); + // The range of the inoise8 function is roughly 16-238. + // These two operations expand those values out to roughly 0..255 + // You can comment them out if you want the raw noise data. + data = qsub8(data, 16); + data = qadd8(data, scale8(data, 39)); + + if (hueReduce > 0 && data >= hueReduce) { + data -= hueReduce; + } + + return ColorFromPalette(palette, data, 255, LINEARBLEND); +} void drawNoise(CRGBPalette16 palette, uint8_t hueReduce = 0) { @@ -81,25 +94,76 @@ void drawNoise(CRGBPalette16 palette, uint8_t hueReduce = 0) int xoffset = noisescale * x; int yoffset = noisescale * y; - uint8_t data = inoise8(x + xoffset + noisex, y + yoffset + noisey, noisez); + leds[i] = noiseXYZ(palette, hueReduce, x + xoffset + noisex, y + yoffset + noisey, noisez); + } - // The range of the inoise8 function is roughly 16-238. - // These two operations expand those values out to roughly 0..255 - // You can comment them out if you want the raw noise data. - data = qsub8(data, 16); - data = qadd8(data, scale8(data, 39)); + noisex += noisespeedx; + noisey += noisespeedy; + noisez += noisespeedz; +} - if (hueReduce > 0 && data >= hueReduce) - data -= hueReduce; +#if HAS_POLAR_COORDS // change to "HAS_CONCENTRIC_RINGS" ? - leds[i] = ColorFromPalette(palette, data, 255, LINEARBLEND); - } +// TODO: The calculations for x/y in drawPolarNoise() depend only upon constant array values. +// Pre-calculate those, and define a proxy for noise() routine that points to this +// pre-calculated array. Then, the code is identical for all noise() functions, differing +// only in the X/Y arrays and palette used. +// drawPolarNoise() uses rings[] +void drawPolarNoise(CRGBPalette16 palette, uint8_t hueReduce = 0) +{ + for (uint8_t ringIndex = 0; ringIndex < ringCount; ringIndex++) { // y == proxy for radius + uint16_t ringStart = rings[ringIndex][0]; + uint16_t ringEnd = rings[ringIndex][1]; + + for (uint16_t i = ringStart; i <= ringEnd; i++) { // x + uint8_t x = (i - ringStart) * (256 / (ringEnd - ringStart)); // proxy for angle[]? + uint8_t y = ringIndex * (128 / ringCount); // 128 / 20 == 6 ... or about half the total range ... could use (radius[] / 2)? + + int xoffset = noisescale * x; + int yoffset = noisescale * y; + + leds[i] = noiseXYZ(palette, hueReduce, x + xoffset + noisex, y + yoffset + noisey, noisez); + } + } + // for (uint8_t ringIndex = 1; ringIndex < ringCount; ringIndex++) { + // uint16_t ringStart = rings[ringIndex][0]; + // uint16_t ringEnd = rings[ringIndex][1]; + // // blend the first pixel in the ring into the last + // nblend(leds[ringStart], leds[ringEnd], 192); + // nblend(leds[ringStart + 1], leds[ringEnd - 1], 128); + // nblend(leds[ringStart + 2], leds[ringEnd - 2], 64); + // } + noisex += noisespeedx; noisey += noisespeedy; noisez += noisespeedz; } +#endif // HAS_POLAR_COORDS + +#if HAS_POLAR_COORDS // uses drawPolarNoise(), which uses rings[] +// TODO: Check if gradientPalettePolarNoise() is equivalent to angleGradientPalette()? +void gradientPalettePolarNoise() { + noisespeedx = 4; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(gCurrentPalette); +} +#endif +#if HAS_POLAR_COORDS // palettePolarNoise() uses drawPolarNoise(), which uses rings[] +void palettePolarNoise() { + noisespeedx = 9; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(palettes[currentPaletteIndex]); +} +#endif + void rainbowNoise() { noisespeedx = 0; noisespeedy = -1; @@ -109,6 +173,17 @@ void rainbowNoise() { drawNoise(RainbowColors_p); } +#if HAS_POLAR_COORDS // rainbowPolarNoise() uses drawPolarNoise(), which uses rings[] +void rainbowPolarNoise() { + noisespeedx = 0; + noisespeedy = 2; + noisespeedz = 0; + noisescale = 0; + colorLoop = 0; + drawPolarNoise(RainbowColors_p); +} +#endif // HAS_POLAR_COORDS + void rainbowStripeNoise() { noisespeedx = 0; noisespeedy = -2; @@ -118,6 +193,17 @@ void rainbowStripeNoise() { drawNoise(RainbowStripeColors_p); } +#if HAS_POLAR_COORDS // rainbowStripePolarNoise() uses drawPolarNoise(), which uses rings[] +void rainbowStripePolarNoise() { + noisespeedx = 0; + noisespeedy = 2; + noisespeedz = 0; + noisescale = 0; + colorLoop = 0; + drawPolarNoise(RainbowStripeColors_p); +} +#endif + void partyNoise() { noisespeedx = -9; noisespeedy = 0; @@ -127,6 +213,17 @@ void partyNoise() { drawNoise(PartyColors_p); } +#if HAS_POLAR_COORDS // partyPolarNoise() uses drawPolarNoise(), which uses rings[] +void partyPolarNoise() { + noisespeedx = 9; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(PartyColors_p); +} +#endif + void forestNoise() { noisespeedx = -9; noisespeedy = 0; @@ -136,6 +233,17 @@ void forestNoise() { drawNoise(ForestColors_p); } +#if HAS_POLAR_COORDS // forestPolarNoise() uses drawPolarNoise(), which uses rings[] +void forestPolarNoise() { + noisespeedx = 9; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(ForestColors_p); +} +#endif + void cloudNoise() { noisespeedx = -2; noisespeedy = 0; @@ -145,6 +253,17 @@ void cloudNoise() { drawNoise(CloudColors_p); } +#if HAS_POLAR_COORDS // cloudPolarNoise() uses drawPolarNoise(), which uses rings[] +void cloudPolarNoise() { + noisespeedx = 2; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 0; + colorLoop = 0; + drawPolarNoise(CloudColors_p); +} +#endif + void fireNoise() { noisespeedx = 0; // 24; noisespeedy = -32; @@ -154,6 +273,22 @@ void fireNoise() { drawNoise(HeatColors_p, 60); } +#if HAS_POLAR_COORDS // firePolarNoise() uses drawPolarNoise(), which uses rings[] +void firePolarNoise() { +// noisespeedx = 0; // 24; +// noisespeedy = -24; +// noisespeedz = 0; +// noisescale = 4; +// colorLoop = 0; + noisespeedx = 0; // 24; + noisespeedy = -32; + noisespeedz = 0; + noisescale = 4; + colorLoop = 0; + drawPolarNoise(HeatColors_p, 60); +} +#endif + void fireNoise2() { noisespeedx = 0; noisespeedy = -8; @@ -163,6 +298,22 @@ void fireNoise2() { drawNoise(HeatColors_p); } +#if HAS_POLAR_COORDS // firePolarNoise2() uses drawPolarNoise(), which uses rings[] +void firePolarNoise2() { +// noisespeedx = 0; +// noisespeedy = -8; +// noisespeedz = 4; +// noisescale = 1; +// colorLoop = 0; + noisespeedx = 0; + noisespeedy = -4; + noisespeedz = 4; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(HeatColors_p); +} +#endif + void lavaNoise() { noisespeedx = 0; noisespeedy = -1; @@ -172,6 +323,17 @@ void lavaNoise() { drawNoise(LavaColors_p); } +#if HAS_POLAR_COORDS // lavaPolarNoise() uses drawPolarNoise(), which uses rings[] +void lavaPolarNoise() { + noisespeedx = 0; + noisespeedy = -1; + noisespeedz = 1; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(LavaColors_p); +} +#endif + void oceanNoise() { noisespeedx = -2; noisespeedy = 0; @@ -181,6 +343,17 @@ void oceanNoise() { drawNoise(OceanColors_p); } +#if HAS_POLAR_COORDS // oceanPolarNoise() uses drawPolarNoise(), which uses rings[] +void oceanPolarNoise() { + noisespeedx = -1; // beatsin8(6, 0, 2) - 1; + noisespeedy = 0; + noisespeedz = 1; + noisescale = 0; + colorLoop = 0; + drawPolarNoise(OceanColors_p); +} +#endif + void blackAndWhiteNoise() { noisespeedx = -12; noisespeedy = 0; @@ -190,6 +363,17 @@ void blackAndWhiteNoise() { drawNoise(blackAndWhiteStripedPalette); } +#if HAS_POLAR_COORDS // blackAndWhitePolarNoise() uses drawPolarNoise(), which uses rings[] +void blackAndWhitePolarNoise() { + noisespeedx = -4; // beatsin8(8, 0, 9) - 4; + noisespeedy = 0; + noisespeedz = 0; + noisescale = 0; + colorLoop = 0; + drawPolarNoise(blackAndWhiteStripedPalette); +} +#endif + void blackAndBlueNoise() { noisespeedx = 0; noisespeedy = 8; @@ -199,5 +383,15 @@ void blackAndBlueNoise() { drawNoise(blackAndBlueStripedPalette); } +#if HAS_POLAR_COORDS // blackAndBluePolarNoise() uses drawPolarNoise(), which uses rings[] +void blackAndBluePolarNoise() { + noisespeedx = 0; + noisespeedy = -8; // beatsin8(8, 0, 16) - 8; + noisespeedz = 0; + noisescale = 1; + colorLoop = 0; + drawPolarNoise(blackAndBlueStripedPalette); +} +#endif #endif // HAS_COORDINATE_MAP \ No newline at end of file diff --git a/esp8266-fastled-webserver/config.h b/esp8266-fastled-webserver/config.h index 0e9a89a6..f162bc90 100644 --- a/esp8266-fastled-webserver/config.h +++ b/esp8266-fastled-webserver/config.h @@ -34,8 +34,8 @@ // #define PRODUCT_FIBONACCI64_NANO // 33mm, SK6805-EC15, ~5mA/pixel // #define PRODUCT_FIBONACCI32 // #define PRODUCT_KRAKEN64 -#define PRODUCT_ESP8266_THING // aka parallel (6-output) - +// #define PRODUCT_ESP8266_THING // aka parallel (6-output) +#define PRODUCT_1628_RINGS // //////////////////////////////////////////////////////////////////////////////////////////////////// // Additional configuration options ... defaults shown @@ -146,6 +146,9 @@ #if !defined(HAS_POLAR_COORDS) || ((HAS_POLAR_COORDS != 0) && (HAS_POLAR_COORDS != 1)) #error "HAS_POLAR_COORDS must be defined to zero or one" #endif + #if HAS_POLAR_COORDS && (!HAS_COORDINATE_MAP) + #error "HAS_POLAR_COORDS is true, so HAS_COORDINATE_MAP must also be true (but is not)" + #endif #if !defined(PARALLEL_OUTPUT_CHANNELS) #error "PARALLEL_OUTPUT_CHANNELS must be defined" #elif (PARALLEL_OUTPUT_CHANNELS == 1) diff --git a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino index b7e90de4..f2b9dd40 100644 --- a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino +++ b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino @@ -117,6 +117,25 @@ PatternAndNameList patterns = { { colorWaves, "Color Waves" }, +#if HAS_POLAR_COORDS // really a wrong name... and likely doing way more computation than necessary + { radarSweepPalette, "Radar Sweep Palette" }, + // noise patterns (XY and 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" }, + { rainbowStripeNoise, "Rainbow Stripe 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" }, @@ -1038,6 +1057,47 @@ void loop() { // TODO: Update magic number from 0x55 to 0xAA (or 0x96 or 0x69) +void readSettings1628Rings() +{ + // 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) { + return; + } + + brightness = EEPROM.read(0); + + currentPatternIndex = EEPROM.read(1); + if (currentPatternIndex >= patternCount) { + currentPatternIndex = patternCount - 1; + } + + byte r = EEPROM.read(2); + byte g = EEPROM.read(3); + byte b = EEPROM.read(4); + + if (r == 0 && g == 0 && b == 0) + { + } + else + { + solidColor = CRGB(r, g, b); + } + + power = EEPROM.read(5); + + autoplay = EEPROM.read(6); + autoplayDuration = EEPROM.read(7); + + currentPaletteIndex = EEPROM.read(8); + if (currentPaletteIndex >= paletteCount) { + currentPaletteIndex = paletteCount - 1; + } + showClock = EEPROM.read(9); + clockBackgroundFade = EEPROM.read(10); + +} void readSettingsEsp8266Thing() // aka parallel { // check for "magic number" so we know settings have been written to EEPROM @@ -1395,7 +1455,9 @@ void readSettingsDefaultProduct() } void readSettings() { - #if defined(PRODUCT_ESP8266_THING) + #if defined (PRODUCT_1628_RINGS) + readSettings1628Rings(); + #elif defined(PRODUCT_ESP8266_THING) readSettingsEsp8266Thing(); #elif defined(PRODUCT_KRAKEN64) readSettingsKraken64(); @@ -1415,7 +1477,22 @@ void readSettings() { #error "readSettings() not defined for product?" #endif } +void writeAndCommitSettings1628Rings() { + EEPROM.write(0, brightness); + EEPROM.write(1, currentPatternIndex); + EEPROM.write(2, solidColor.r); + EEPROM.write(3, solidColor.g); + EEPROM.write(4, solidColor.b); + EEPROM.write(5, power); + EEPROM.write(6, autoplay); + EEPROM.write(7, autoplayDuration); + EEPROM.write(8, currentPaletteIndex); + EEPROM.write(9, showClock); + EEPROM.write(10, clockBackgroundFade); + EEPROM.write(511, 55); + EEPROM.commit(); +} void writeAndCommitSettingsEsp8266Thing() // aka parallel { EEPROM.write(0, brightness); @@ -1571,7 +1648,9 @@ void writeAndCommitSettingsDefaultProduct() void writeAndCommitSettings() { - #if defined(PRODUCT_ESP8266_THING) + #if defined (PRODUCT_1628_RINGS) + writeAndCommitSettings1628Rings(); + #elif defined(PRODUCT_ESP8266_THING) writeAndCommitSettingsEsp8266Thing(); #elif defined(PRODUCT_KRAKEN64) writeAndCommitSettingsKraken64(); @@ -2084,9 +2163,6 @@ void palettetest( CRGB* ledarray, uint16_t numleds, const CRGBPalette16& gCurren fill_palette( ledarray, numleds, startindex, (256 / NUM_PIXELS) + 1, gCurrentPalette, 255, LINEARBLEND); } - -// TODO - swirlFibonacci(): Disable if NUM_PIXELS < 128? - #if IS_FIBONACCI // swirlFibonacci() uses physicalToFibonacci and angles void swirlFibonacci() { @@ -2118,8 +2194,6 @@ void swirlFibonacci() { } #endif -// TODO - fireFibonacci(): Disable if NUM_PIXELS < 128? - #if IS_FIBONACCI // fireFibonacci() uses coordsX/coordsY // TODO: combine with normal fire effect void fireFibonacci() { @@ -2134,8 +2208,6 @@ void fireFibonacci() { } #endif -// TODO - waterFibonacci(): Disable if NUM_PIXELS < 128? - #if IS_FIBONACCI // waterFibonacci() uses coordsX/coordsY // TODO: combine with normal water effect void waterFibonacci() { @@ -2150,8 +2222,6 @@ void waterFibonacci() { } #endif -// TODO - emitterFibonacci(): Disable if NUM_PIXELS < 128? - #if IS_FIBONACCI // emitterFibonacci() uses angle, antialiasPixelAR() /** * Emits arcs of color spreading out from the center to the edge of the disc. diff --git a/esp8266-fastled-webserver/include/configs/product/1628rings.h b/esp8266-fastled-webserver/include/configs/product/1628rings.h index 6180cefe..af3b02d4 100644 --- a/esp8266-fastled-webserver/include/configs/product/1628rings.h +++ b/esp8266-fastled-webserver/include/configs/product/1628rings.h @@ -57,12 +57,13 @@ #define IS_FIBONACCI 0 #endif #if !defined(HAS_COORDINATE_MAP) - #define HAS_COORDINATE_MAP 0 + #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) +#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 From 968388d4f22aedecd106f9d84d16112ad655b6bf Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Thu, 21 Oct 2021 11:47:39 -0700 Subject: [PATCH 09/16] saturate at 256 --- esp8266-fastled-webserver/Map.h | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/esp8266-fastled-webserver/Map.h b/esp8266-fastled-webserver/Map.h index 8c7bb03a..b6309d70 100644 --- a/esp8266-fastled-webserver/Map.h +++ b/esp8266-fastled-webserver/Map.h @@ -328,7 +328,13 @@ void radiusPalette() { uint16_t hues = 1; for (uint16_t i = 0; i < NUM_PIXELS; i++) { - uint8_t r = ((unsigned)(radiusProxy[i] * RADII_SCALE_MULTIPLIER)) / RADII_SCALE_DIVISOR; + + unsigned tmp = ((unsigned)(radiusProxy[i] * RADII_SCALE_MULTIPLIER)) / RADII_SCALE_DIVISOR; +#if ((NUM_PIXELS & (NUM_PIXELS-1) == 0) // Power-of-two, so no need to check + uint8_t r = tmp; +#else + uint8_t r = tmp > 255 ? 255 : tmp; +#endif leds[i] = ColorFromPalette(palettes[currentPaletteIndex], beat8(speed) - (r * hues)); } } @@ -388,7 +394,13 @@ void radiusGradientPalette() { uint16_t hues = 1; for (uint16_t i = 0; i < NUM_PIXELS; i++) { - uint8_t r = ((unsigned)(radiusProxy[i] * RADII_SCALE_MULTIPLIER)) / RADII_SCALE_DIVISOR; + unsigned r = ((unsigned)(radiusProxy[i] * RADII_SCALE_MULTIPLIER)) / RADII_SCALE_DIVISOR; +#if ((NUM_PIXELS & (NUM_PIXELS-1) == 0) // Power-of-two, so no need to check + uint8_t r = tmp; +#else + uint8_t r = tmp > 255 ? 255 : tmp; +#endif + leds[i] = ColorFromPalette(gCurrentPalette, beat8(speed) - (r * hues)); } } From 4db21d0f80279c60336064db59b93e7c09f786ba Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Thu, 21 Oct 2021 14:39:42 -0700 Subject: [PATCH 10/16] Fixes for Fib512 and Fib32 * Fib512 - drawAnalogClock() fix * Fib512 - multi_test() fix * Fib32 - fix a couple typos / missed declarations --- esp8266-fastled-webserver/Map.h | 23 ++++++++----- esp8266-fastled-webserver/config.h | 4 +-- .../esp8266-fastled-webserver.ino | 32 +++++++++++++++---- 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/esp8266-fastled-webserver/Map.h b/esp8266-fastled-webserver/Map.h index b6309d70..85690ff7 100644 --- a/esp8266-fastled-webserver/Map.h +++ b/esp8266-fastled-webserver/Map.h @@ -93,6 +93,9 @@ const uint8_t coordsX[NUM_PIXELS] { 152, 224, 252, 210, 211, 184, 169, 161, 89, 121, 138, 102, 61, 19, 13, 57, 82, 29, 0, 36, 63, 111, 79, 83, 158, 129, 118, 160, 196, 255, 212, 163, 203, 250 }; const uint8_t coordsY[NUM_PIXELS] { 120, 101, 69, 7, 48, 90, 50, 7, 0, 27, 83, 62, 37, 35, 84, 78, 112, 125, 154, 185, 149, 140, 195, 236, 255, 226, 179, 198, 223, 181, 183, 156, 144, 135 }; const uint8_t angles[NUM_PIXELS] { 255, 246, 237, 214, 223, 232, 208, 199, 176, 185, 193, 170, 161, 152, 138, 147, 132, 123, 114, 100, 108, 94, 85, 76, 53, 62, 70, 47, 38, 15, 23, 32, 9, 0 }; + static const auto (&radiusProxy)[NUM_PIXELS] = physicalToFibonacci; + static const uint8_t RADII_SCALE_DIVISOR { 1 }; + static const uint8_t RADII_SCALE_MULTIPLIER { 8 }; #elif defined(PRODUCT_KRAKEN64) const uint8_t coordsX[NUM_PIXELS] { 151, 188, 199, 199, 171, 147, 131, 119, 124, 179, 200, 217, 237, 249, 242, 234, 255, 148, 175, 177, 150, 143, 171, 153, 155, 106, 110, 102, 75, 86, 106, 108, 88, 90, 84, 78, 107, 98, 121, 128, 80, 69, 134, 159, 192, 202, 195, 218, 61, 32, 18, 26, 39, 20, 3, 0, 48, 52, 61, 54, 33, 20, 7, 8 }; const uint8_t coordsY[NUM_PIXELS] { 190, 204, 225, 252, 255, 236, 216, 191, 166, 147, 154, 170, 173, 156, 131, 107, 106, 148, 121, 86, 81, 63, 56, 36, 17, 145, 120, 96, 55, 23, 18, 0, 2, 112, 77, 31, 35, 49, 51, 30, 124, 103, 101, 98, 80, 58, 40, 69, 134, 124, 107, 81, 56, 43, 50, 70, 156, 180, 202, 219, 213, 195, 197, 215 }; @@ -330,7 +333,7 @@ void radiusPalette() { for (uint16_t i = 0; i < NUM_PIXELS; i++) { unsigned tmp = ((unsigned)(radiusProxy[i] * RADII_SCALE_MULTIPLIER)) / RADII_SCALE_DIVISOR; -#if ((NUM_PIXELS & (NUM_PIXELS-1) == 0) // Power-of-two, so no need to check +#if ((NUM_PIXELS & (NUM_PIXELS-1)) == 0) // Power-of-two, so no need to check uint8_t r = tmp; #else uint8_t r = tmp > 255 ? 255 : tmp; @@ -394,8 +397,8 @@ void radiusGradientPalette() { uint16_t hues = 1; for (uint16_t i = 0; i < NUM_PIXELS; i++) { - unsigned r = ((unsigned)(radiusProxy[i] * RADII_SCALE_MULTIPLIER)) / RADII_SCALE_DIVISOR; -#if ((NUM_PIXELS & (NUM_PIXELS-1) == 0) // Power-of-two, so no need to check + unsigned tmp = ((unsigned)(radiusProxy[i] * RADII_SCALE_MULTIPLIER)) / RADII_SCALE_DIVISOR; +#if ((NUM_PIXELS & (NUM_PIXELS-1)) == 0) // Power-of-two, so no need to check uint8_t r = tmp; #else uint8_t r = tmp > 255 ? 255 : tmp; @@ -446,10 +449,14 @@ void xyGradientPalette() { #if IS_FIBONACCI // drawAnalogClock() calls antialiasPixelAR(), which requires physicalToFibonacci[] void drawAnalogClock() { - static_assert(NUM_PIXELS >= 32, "Update to drawAnalogClock() required to support fewer pixels"); - const uint8_t hourRadius = NUM_PIXELS / 8 * 3; // 96 designed for 256 pixels ==> 3/8 - const uint8_t minuteRadius = NUM_PIXELS / 4 * 3; // 192 designed for 256 pixels ==> 3/4 - const uint8_t secondRadius = NUM_PIXELS - 1; // 255 designed for 256 pixels ==> all pixels + // TODO: Update to use radiusProxy? For now, just divide 512+ by RADII_SCALE_DIVISOR + + static_assert((NUM_PIXELS / RADII_SCALE_DIVISOR) <= 256, ""); + static_assert((NUM_PIXELS / RADII_SCALE_DIVISOR) >= 32, "Update to drawAnalogClock() required to support fewer pixels"); + + const uint8_t hourRadius = (uint8_t)(NUM_PIXELS / RADII_SCALE_DIVISOR / 8u * 3u); // 96 designed for 256 pixels ==> 3/8 + const uint8_t minuteRadius = (uint8_t)(NUM_PIXELS / RADII_SCALE_DIVISOR / 4u * 3u); // 192 designed for 256 pixels ==> 3/4 + const uint8_t secondRadius = (uint8_t)(NUM_PIXELS / RADII_SCALE_DIVISOR - 1); // 255 designed for 256 pixels ==> all pixels const uint8_t hourHandWidth = 8; // angle @ unit256 ~= 11.25000 degrees const uint8_t minuteHandWidth = 7; // angle @ unit256 ~= 9.84375 degrees @@ -473,8 +480,8 @@ void drawAnalogClock() { secondAngle = 256u - second * degreesPerSecond; } + // although can update angles once every 100ms, have to perform fade & overlay with each cycle fadeToBlackBy(leds, NUM_PIXELS, clockBackgroundFade); - antialiasPixelAR(secondAngle, secondHandWidth, 0, secondRadius, CRGB::Blue ); antialiasPixelAR(minuteAngle, minuteHandWidth, 0, minuteRadius, CRGB::Green); antialiasPixelAR(hourAngle, hourHandWidth, 0, hourRadius, CRGB::Red ); diff --git a/esp8266-fastled-webserver/config.h b/esp8266-fastled-webserver/config.h index f162bc90..7def55e1 100644 --- a/esp8266-fastled-webserver/config.h +++ b/esp8266-fastled-webserver/config.h @@ -24,7 +24,7 @@ // When compiling from Arduino, you can edit this file. // When compiling from PlatformIO, this is a reference for compiler flags. -// #define PRODUCT_DEFAULT +#define PRODUCT_DEFAULT // #define PRODUCT_FIBONACCI512 // #define PRODUCT_FIBONACCI256 // #define PRODUCT_FIBONACCI128 @@ -35,7 +35,7 @@ // #define PRODUCT_FIBONACCI32 // #define PRODUCT_KRAKEN64 // #define PRODUCT_ESP8266_THING // aka parallel (6-output) -#define PRODUCT_1628_RINGS +// #define PRODUCT_1628_RINGS // //////////////////////////////////////////////////////////////////////////////////////////////////// // Additional configuration options ... defaults shown diff --git a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino index f2b9dd40..e9b021a8 100644 --- a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino +++ b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino @@ -2274,6 +2274,7 @@ void wheel() { #if (PARALLEL_OUTPUT_CHANNELS > 1) + void multi_test() { static bool debug = true; const uint8_t step = (256 / PARALLEL_OUTPUT_CHANNELS); @@ -2290,22 +2291,38 @@ void multi_test() { if (strip == 0) { pixelOffset = LedOffset<1>(); // uses one-based indices... sigh. pixelCount = LedCount<1>(); // uses one-based indices... sigh. - } else if (strip == 1) { + } +#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. - } else if (strip == 2) { + } +#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. - } else if (strip == 3) { + } +#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. - } else if (strip == 4) { + } +#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. - } else if (strip == 5) { + } +#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. - } else { + } +#endif + else { break; } @@ -2330,4 +2347,5 @@ void multi_test() { debug = false; } -#endif \ No newline at end of file +#endif + From ebd45fb4ba7b269cc62feed253e2c564cbf6661b Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Thu, 21 Oct 2021 14:45:06 -0700 Subject: [PATCH 11/16] delete the empty file --- PolarNoise.h | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 PolarNoise.h diff --git a/PolarNoise.h b/PolarNoise.h deleted file mode 100644 index 3ddf4f28..00000000 --- a/PolarNoise.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - Sol: https://github.com/evilgeniuslabs/sol - Copyright (C) 2016 Jason Coon, Evil Genius Labs - - 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 . -*/ - - - - - - - - -#endif // HAS_POLAR_COORDS \ No newline at end of file From a34f65a47da021170cd0bc13956ea3675dcb4219 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Sat, 6 Nov 2021 20:03:38 -0700 Subject: [PATCH 12/16] Squashed commit from branch combined_dev7 * PERF -- fewer allocations when reading .gz file * PERF -- have polar noise use existing `radii[]` * PERF -- polar noise now uses pre-calculated angles * BUGFIX -- count of pixels in rings 14, 15 This fixes the mismatch between `rings[][2]` and other coordinates in map.cpp (coordX, coordY, radii, angles). * Renaming .h --> .hpp for various headers * Split headers (.h) from implementation (.cpp) * Using common EEPROM settings for all products * comment updates * .gitignore updates --- .gitignore | 4 +- ...sPlayground.h => ColorWavesPlayground.cpp} | 2 + .../{FSBrowser.h => FSBrowser.cpp} | 67 +- esp8266-fastled-webserver/Field.h | 132 --- .../{Fields.h => Fields.cpp} | 200 +++- ...radientPalettes.h => GradientPalettes.cpp} | 2 + .../{Info.h => Info.cpp} | 2 + esp8266-fastled-webserver/{Map.h => Map.cpp} | 41 +- .../{Noise.h => Noise.cpp} | 109 +- .../{Pacifica.h => Pacifica.cpp} | 1 + .../{Ping.h => Ping.cpp} | 1 + ...{PridePlayground.h => PridePlayground.cpp} | 2 + .../{TwinkleFOX.h => TwinkleFOX.cpp} | 17 +- .../{Twinkles.h => Twinkles.cpp} | 2 + .../{Commands.h => commands.cpp} | 420 ++++++-- esp8266-fastled-webserver/common.h | 303 +++++- esp8266-fastled-webserver/config.h | 10 +- .../esp8266-fastled-webserver.ino | 973 ++---------------- .../include/FSBrowser.hpp | 18 + esp8266-fastled-webserver/include/Fields.hpp | 33 + .../include/GradientPalettes.hpp | 39 + 21 files changed, 1044 insertions(+), 1334 deletions(-) rename esp8266-fastled-webserver/{ColorWavesPlayground.h => ColorWavesPlayground.cpp} (99%) rename esp8266-fastled-webserver/{FSBrowser.h => FSBrowser.cpp} (77%) delete mode 100644 esp8266-fastled-webserver/Field.h rename esp8266-fastled-webserver/{Fields.h => Fields.cpp} (60%) rename esp8266-fastled-webserver/{GradientPalettes.h => GradientPalettes.cpp} (99%) rename esp8266-fastled-webserver/{Info.h => Info.cpp} (99%) rename esp8266-fastled-webserver/{Map.h => Map.cpp} (98%) rename esp8266-fastled-webserver/{Noise.h => Noise.cpp} (80%) rename esp8266-fastled-webserver/{Pacifica.h => Pacifica.cpp} (99%) rename esp8266-fastled-webserver/{Ping.h => Ping.cpp} (99%) rename esp8266-fastled-webserver/{PridePlayground.h => PridePlayground.cpp} (99%) rename esp8266-fastled-webserver/{TwinkleFOX.h => TwinkleFOX.cpp} (95%) rename esp8266-fastled-webserver/{Twinkles.h => Twinkles.cpp} (99%) rename esp8266-fastled-webserver/{Commands.h => commands.cpp} (52%) create mode 100644 esp8266-fastled-webserver/include/FSBrowser.hpp create mode 100644 esp8266-fastled-webserver/include/Fields.hpp create mode 100644 esp8266-fastled-webserver/include/GradientPalettes.hpp diff --git a/.gitignore b/.gitignore index 713f0297..f5850d48 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,6 @@ buildcache/ arduino.json c_cpp_properties.json .vscode -/platformio-override.ini \ No newline at end of file + +/platformio-override.ini +/release/ diff --git a/esp8266-fastled-webserver/ColorWavesPlayground.h b/esp8266-fastled-webserver/ColorWavesPlayground.cpp similarity index 99% rename from esp8266-fastled-webserver/ColorWavesPlayground.h rename to esp8266-fastled-webserver/ColorWavesPlayground.cpp index 6c1b64e9..a0de53ce 100644 --- a/esp8266-fastled-webserver/ColorWavesPlayground.h +++ b/esp8266-fastled-webserver/ColorWavesPlayground.cpp @@ -1,3 +1,5 @@ +#include "common.h" + // 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. diff --git a/esp8266-fastled-webserver/FSBrowser.h b/esp8266-fastled-webserver/FSBrowser.cpp similarity index 77% rename from esp8266-fastled-webserver/FSBrowser.h rename to esp8266-fastled-webserver/FSBrowser.cpp index 08fa4f7d..3400004e 100644 --- a/esp8266-fastled-webserver/FSBrowser.h +++ b/esp8266-fastled-webserver/FSBrowser.cpp @@ -1,3 +1,4 @@ +#include "common.h" //holds the current upload File fsUploadFile; @@ -34,12 +35,15 @@ String getContentType(String filename){ bool handleFileRead(String path){ Serial.println("handleFileRead: " + path); - if(path.endsWith("/")) path += "index.htm"; + if (path.endsWith("/")) { + path += "index.htm"; + } String contentType = getContentType(path); String pathWithGz = path + ".gz"; - if(MYFS.exists(pathWithGz) || MYFS.exists(path)){ - if(MYFS.exists(pathWithGz)) - path += ".gz"; + if (MYFS.exists(pathWithGz) || MYFS.exists(path)) { + if (MYFS.exists(pathWithGz)) { + path = pathWithGz; + } File file = MYFS.open(path, "r"); (void)webServer.streamFile(file, contentType); file.close(); @@ -50,58 +54,75 @@ bool handleFileRead(String path){ } void handleFileUpload(){ - if(webServer.uri() != "/edit") return; + if (webServer.uri() != "/edit") return; + HTTPUpload& upload = webServer.upload(); - if(upload.status == UPLOAD_FILE_START){ + if (upload.status == UPLOAD_FILE_START) { String filename = upload.filename; - if(!filename.startsWith("/")) filename = "/"+filename; + if (!filename.startsWith("/")) { + filename = "/" + filename; + } Serial.print("handleFileUpload Name: "); Serial.println(filename); fsUploadFile = MYFS.open(filename, "w"); filename = String(); - } else if(upload.status == UPLOAD_FILE_WRITE){ + } else if (upload.status == UPLOAD_FILE_WRITE) { //Serial.print("handleFileUpload Data: "); Serial.println(upload.currentSize); - if(fsUploadFile) + if (fsUploadFile) { fsUploadFile.write(upload.buf, upload.currentSize); - } else if(upload.status == UPLOAD_FILE_END){ - if(fsUploadFile) + } + } else if (upload.status == UPLOAD_FILE_END) { + if (fsUploadFile) { fsUploadFile.close(); + } Serial.print("handleFileUpload Size: "); Serial.println(upload.totalSize); } } void handleFileDelete(){ - if(webServer.args() == 0) return webServer.send(500, "text/plain", "BAD ARGS"); + if (webServer.args() == 0) { + return webServer.send(500, "text/plain", "BAD ARGS"); + } + String path = webServer.arg(0); Serial.println("handleFileDelete: " + path); - if(path == "/") + if (path == "/") { return webServer.send(500, "text/plain", "BAD PATH"); - if(!MYFS.exists(path)) + } + if (!MYFS.exists(path)) { return webServer.send(404, "text/plain", "FileNotFound"); + } MYFS.remove(path); webServer.send(200, "text/plain", ""); path = String(); } void handleFileCreate(){ - if(webServer.args() == 0) + if (webServer.args() == 0) { return webServer.send(500, "text/plain", "BAD ARGS"); + } String path = webServer.arg(0); Serial.println("handleFileCreate: " + path); - if(path == "/") + if (path == "/") { return webServer.send(500, "text/plain", "BAD PATH"); - if(MYFS.exists(path)) + } + if (MYFS.exists(path)) { return webServer.send(500, "text/plain", "FILE EXISTS"); + } File file = MYFS.open(path, "w"); - if(file) + if (file) { file.close(); - else + } else { return webServer.send(500, "text/plain", "CREATE FAILED"); + } webServer.send(200, "text/plain", ""); path = String(); } void handleFileList() { - if(!webServer.hasArg("dir")) {webServer.send(500, "text/plain", "BAD ARGS"); return;} + if (!webServer.hasArg("dir")) { + webServer.send(500, "text/plain", "BAD ARGS"); + return; + } String path = webServer.arg("dir"); Serial.println("handleFileList: " + path); @@ -109,9 +130,11 @@ void handleFileList() { path = String(); String output = "["; - while(dir.next()){ + while (dir.next()) { File entry = dir.openFile("r"); - if (output != "[") output += ','; + if (output != "[") { + output += ','; + } bool isDir = false; //bool isDir = entry.isDirectory(); diff --git a/esp8266-fastled-webserver/Field.h b/esp8266-fastled-webserver/Field.h deleted file mode 100644 index c3a04ce9..00000000 --- a/esp8266-fastled-webserver/Field.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - 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 . -*/ - -typedef String (*FieldSetter)(String); -typedef String (*FieldGetter)(); - -const String NumberFieldType = "Number"; -const String BooleanFieldType = "Boolean"; -const String SelectFieldType = "Select"; -const String ColorFieldType = "Color"; -const String SectionFieldType = "Section"; -const String StringFieldType = "String"; -const String LabelFieldType = "Label"; - -struct Field { - String name; - String label; - String type; - uint8_t min; - uint8_t max; - FieldGetter getValue; - FieldGetter getOptions; - FieldSetter setValue; -}; - -typedef Field FieldList[]; - -Field getField(String name, FieldList fields, uint8_t count) { - for (uint8_t i = 0; i < count; i++) { - Field field = fields[i]; - if (field.name == name) { - return field; - } - } - return Field(); -} - -String getFieldValue(String name, FieldList fields, uint8_t count) { - Field field = getField(name, fields, count); - if (field.getValue) { - return field.getValue(); - } - return String(); -} - -String setFieldValue(String name, String value, FieldList fields, uint8_t count) { - Field field = getField(name, fields, count); - if (field.setValue) { - return field.setValue(value); - } - return String(); -} - -String getFieldsJson(FieldList fields, uint8_t count) { - String json = "["; - - for (uint8_t i = 0; i < count; i++) { - Field field = fields[i]; - - json += "{\"name\":\"" + field.name + "\",\"label\":\"" + field.label + "\",\"type\":\"" + field.type + "\""; - - if(field.getValue) { - if (field.type == ColorFieldType || field.type == StringFieldType || field.type == LabelFieldType) { - json += ",\"value\":\"" + field.getValue() + "\""; - } - else { - json += ",\"value\":" + field.getValue(); - } - } - - if (field.type == NumberFieldType) { - json += ",\"min\":" + String(field.min); - json += ",\"max\":" + String(field.max); - } - - if (field.getOptions) { - json += ",\"options\":["; - json += field.getOptions(); - json += "]"; - } - - json += "}"; - - if (i < count - 1) - json += ","; - } - - json += "]"; - - return json; -} - -/* - String json = "["; - - json += "{\"name\":\"power\",\"label\":\"Power\",\"type\":\"Boolean\",\"value\":" + String(power) + "},"; - json += "{\"name\":\"brightness\",\"label\":\"Brightness\",\"type\":\"Number\",\"value\":" + String(brightness) + "},"; - - json += "{\"name\":\"pattern\",\"label\":\"Pattern\",\"type\":\"Select\",\"value\":" + String(currentPatternIndex) + ",\"options\":["; - for (uint8_t i = 0; i < patternCount; i++) - { - json += "\"" + patterns[i].name + "\""; - if (i < patternCount - 1) - json += ","; - } - json += "]},"; - - json += "{\"name\":\"autoplay\",\"label\":\"Autoplay\",\"type\":\"Boolean\",\"value\":" + String(autoplay) + "},"; - json += "{\"name\":\"autoplayDuration\",\"label\":\"Autoplay Duration\",\"type\":\"Number\",\"value\":" + String(autoplayDuration) + "},"; - - json += "{\"name\":\"solidColor\",\"label\":\"Color\",\"type\":\"Color\",\"value\":\"" + String(solidColor.r) + "," + String(solidColor.g) + "," + String(solidColor.b) +"\"},"; - - json += "{\"name\":\"cooling\",\"label\":\"Cooling\",\"type\":\"Number\",\"value\":" + String(cooling) + "},"; - json += "{\"name\":\"sparking\",\"label\":\"Sparking\",\"type\":\"Number\",\"value\":" + String(sparking) + "}"; - - json += "]"; -*/ diff --git a/esp8266-fastled-webserver/Fields.h b/esp8266-fastled-webserver/Fields.cpp similarity index 60% rename from esp8266-fastled-webserver/Fields.h rename to esp8266-fastled-webserver/Fields.cpp index 3537de73..f20af72a 100644 --- a/esp8266-fastled-webserver/Fields.h +++ b/esp8266-fastled-webserver/Fields.cpp @@ -15,10 +15,21 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +#include "common.h" + +const String NumberFieldType = "Number"; +const String BooleanFieldType = "Boolean"; +const String SelectFieldType = "Select"; +const String ColorFieldType = "Color"; +const String SectionFieldType = "Section"; +const String StringFieldType = "String"; +const String LabelFieldType = "Label"; uint8_t power = 1; uint8_t brightness = brightnessMap[brightnessIndex]; + + //String setPower(String value) { // power = value.toInt(); // if(power < 0) power = 0; @@ -148,130 +159,232 @@ String getSaturationBpm() { } String setSaturationBpm(String value) { - saturationBpm = value.toInt(); return value; + saturationBpm = value.toInt(); + return value; } String getSaturationMin() { return String(saturationMin); } String setSaturationMin(String value) { - saturationMin = value.toInt(); return value; + saturationMin = value.toInt(); + return value; } String getSaturationMax() { return String(saturationMax); } String setSaturationMax(String value) { - saturationMax = value.toInt(); return value; + saturationMax = value.toInt(); + return value; } String getBrightDepthBpm() { return String(brightDepthBpm); } String setBrightDepthBpm(String value) { - brightDepthBpm = value.toInt(); return value; + brightDepthBpm = value.toInt(); + return value; } String getBrightDepthMin() { return String(brightDepthMin); } String setBrightDepthMin(String value) { - brightDepthMin = value.toInt(); return value; + brightDepthMin = value.toInt(); + return value; } String getBrightDepthMax() { return String(brightDepthMax); } String setBrightDepthMax(String value) { - brightDepthMax = value.toInt(); return value; + brightDepthMax = value.toInt(); + return value; } String getBrightThetaIncBpm() { return String(brightThetaIncBpm); } String setBrightThetaIncBpm(String value) { - brightThetaIncBpm = value.toInt(); return value; + brightThetaIncBpm = value.toInt(); + return value; } String getBrightThetaIncMin() { return String(brightThetaIncMin); } String setBrightThetaIncMin(String value) { - brightThetaIncMin = value.toInt(); return value; + brightThetaIncMin = value.toInt(); + return value; } String getBrightThetaIncMax() { return String(brightThetaIncMax); } String setBrightThetaIncMax(String value) { - brightThetaIncMax = value.toInt(); return value; + brightThetaIncMax = value.toInt(); + return value; } String getMsMultiplierBpm() { return String(msMultiplierBpm); } String setMsMultiplierBpm(String value) { - msMultiplierBpm = value.toInt(); return value; + msMultiplierBpm = value.toInt(); + return value; } String getMsMultiplierMin() { return String(msMultiplierMin); } String setMsMultiplierMin(String value) { - msMultiplierMin = value.toInt(); return value; + msMultiplierMin = value.toInt(); + return value; } String getMsMultiplierMax() { return String(msMultiplierMax); } String setMsMultiplierMax(String value) { - msMultiplierMax = value.toInt(); return value; + msMultiplierMax = value.toInt(); + return value; } String getHueIncBpm() { return String(hueIncBpm); } String setHueIncBpm(String value) { - hueIncBpm = value.toInt(); return value; + hueIncBpm = value.toInt(); + return value; } String getHueIncMin() { return String(hueIncMin); } String setHueIncMin(String value) { - hueIncMin = value.toInt(); return value; + hueIncMin = value.toInt(); + return value; } String getHueIncMax() { return String(hueIncMax); } String setHueIncMax(String value) { - hueIncMax = value.toInt(); return value; + hueIncMax = value.toInt(); + return value; } String getSHueBpm() { return String(sHueBpm); } String setSHueBpm(String value) { - sHueBpm = value.toInt(); return value; + sHueBpm = value.toInt(); + return value; } String getSHueMin() { return String(sHueMin); } String setSHueMin(String value) { - sHueMin = value.toInt(); return value; + sHueMin = value.toInt(); + return value; } String getSHueMax() { return String(sHueMax); } String setSHueMax(String value) { - sHueMax = value.toInt(); return value; + sHueMax = value.toInt(); + return value; +} + + +typedef String (*FieldSetter)(String); +typedef String (*FieldGetter)(); +struct Field { + String name; + String label; + String type; + uint8_t min; + uint8_t max; + FieldGetter getValue; + FieldGetter getOptions; + FieldSetter setValue; +}; + +// passing array reference works fine, but need to make the function a template +// to capture the array size... on the positive side, no need to pass `count` parameter +template +Field getField(String name, const Field (&fields)[N]) { + for (uint8_t i = 0; i < N; i++) { + Field field = fields[i]; + if (field.name == name) { + return field; + } + } + return Field(); +} +template +String getFieldValue(String name, const Field (&fields)[N]) { + Field field = getField(name, fields); + if (field.getValue) { + return field.getValue(); + } + return String(); +} +template +String setFieldValue(String name, String value, const Field (&fields)[N]) { + Field field = getField(name, fields); + if (field.setValue) { + return field.setValue(value); + } + return String(); +} +template +String getFieldsJson(const Field (&fields)[N]) { + String json = "["; + + for (uint8_t i = 0; i < N; i++) { + Field field = fields[i]; + + json += "{\"name\":\"" + field.name + "\",\"label\":\"" + field.label + "\",\"type\":\"" + field.type + "\""; + + if(field.getValue) { + if (field.type == ColorFieldType || field.type == StringFieldType || field.type == LabelFieldType) { + json += ",\"value\":\"" + field.getValue() + "\""; + } + else { + json += ",\"value\":" + field.getValue(); + } + } + + if (field.type == NumberFieldType) { + json += ",\"min\":" + String(field.min); + json += ",\"max\":" + String(field.max); + } + + if (field.getOptions) { + json += ",\"options\":["; + json += field.getOptions(); + json += "]"; + } + + json += "}"; + + if (i < N - 1) + json += ","; + } + + json += "]"; + + return json; } // name, label, type, min, max, getValue, getOptions, setValue -FieldList fields = { +// only items that use the 'getOptions': patterns and palettes +// only items that support 'setValue': options used for pridePlayground +const Field fields[] = { {"name", "Name", LabelFieldType, 0, 0, getName, nullptr, nullptr}, {"power", "Power", BooleanFieldType, 0, 1, getPower, nullptr, nullptr}, @@ -307,31 +420,46 @@ FieldList fields = { //-------------------------------------------------------------------------------------------------------- - {"prideSection", "Pride", SectionFieldType, 0, 0, nullptr, nullptr, nullptr}, + {"prideSection", "Pride Playground", SectionFieldType, 0, 0, nullptr, nullptr, nullptr}, - {"saturationBpm", "Saturation BPM", NumberFieldType, 0, 255, getSaturationBpm, nullptr, setSaturationBpm}, - {"saturationMin", "Saturation Min", NumberFieldType, 0, 255, getSaturationMin, nullptr, setSaturationMin}, - {"saturationMax", "Saturation Max", NumberFieldType, 0, 255, getSaturationMax, nullptr, setSaturationMax}, + {"saturationBpm", "Saturation BPM", NumberFieldType, 0, 255, getSaturationBpm, nullptr, setSaturationBpm}, + {"saturationMin", "Saturation Min", NumberFieldType, 0, 255, getSaturationMin, nullptr, setSaturationMin}, + {"saturationMax", "Saturation Max", NumberFieldType, 0, 255, getSaturationMax, nullptr, setSaturationMax}, - {"brightDepthBpm", "Brightness Depth BPM", NumberFieldType, 0, 255, getBrightDepthBpm, nullptr, setBrightDepthBpm}, - {"brightDepthMin", "Brightness Depth Min", NumberFieldType, 0, 255, getBrightDepthMin, nullptr, setBrightDepthMin}, - {"brightDepthMax", "Brightness Depth Max", NumberFieldType, 0, 255, getBrightDepthMax, nullptr, setBrightDepthMax}, + {"brightDepthBpm", "Brightness Depth BPM", NumberFieldType, 0, 255, getBrightDepthBpm, nullptr, setBrightDepthBpm}, + {"brightDepthMin", "Brightness Depth Min", NumberFieldType, 0, 255, getBrightDepthMin, nullptr, setBrightDepthMin}, + {"brightDepthMax", "Brightness Depth Max", NumberFieldType, 0, 255, getBrightDepthMax, nullptr, setBrightDepthMax}, {"brightThetaIncBpm", "Bright Theta Inc BPM", NumberFieldType, 0, 255, getBrightThetaIncBpm, nullptr, setBrightThetaIncBpm}, {"brightThetaIncMin", "Bright Theta Inc Min", NumberFieldType, 0, 255, getBrightThetaIncMin, nullptr, setBrightThetaIncMin}, {"brightThetaIncMax", "Bright Theta Inc Max", NumberFieldType, 0, 255, getBrightThetaIncMax, nullptr, setBrightThetaIncMax}, - {"msMultiplierBpm", "Time Multiplier BPM", NumberFieldType, 0, 255, getMsMultiplierBpm, nullptr, setMsMultiplierBpm}, - {"msMultiplierMin", "Time Multiplier Min", NumberFieldType, 0, 255, getMsMultiplierMin, nullptr, setMsMultiplierMin}, - {"msMultiplierMax", "Time Multiplier Max", NumberFieldType, 0, 255, getMsMultiplierMax, nullptr, setMsMultiplierMax}, + {"msMultiplierBpm", "Time Multiplier BPM", NumberFieldType, 0, 255, getMsMultiplierBpm, nullptr, setMsMultiplierBpm}, + {"msMultiplierMin", "Time Multiplier Min", NumberFieldType, 0, 255, getMsMultiplierMin, nullptr, setMsMultiplierMin}, + {"msMultiplierMax", "Time Multiplier Max", NumberFieldType, 0, 255, getMsMultiplierMax, nullptr, setMsMultiplierMax}, - {"hueIncBpm", "Hue Inc BPM", NumberFieldType, 0, 255, getHueIncBpm, nullptr, setHueIncBpm}, - {"hueIncMin", "Hue Inc Min", NumberFieldType, 0, 255, getHueIncMin, nullptr, setHueIncMin}, - {"hueIncMax", "Hue Inc Max", NumberFieldType, 0, 255, getHueIncMax, nullptr, setHueIncMax}, + {"hueIncBpm", "Hue Inc BPM", NumberFieldType, 0, 255, getHueIncBpm, nullptr, setHueIncBpm}, + {"hueIncMin", "Hue Inc Min", NumberFieldType, 0, 255, getHueIncMin, nullptr, setHueIncMin}, + {"hueIncMax", "Hue Inc Max", NumberFieldType, 0, 255, getHueIncMax, nullptr, setHueIncMax}, - {"sHueBpm", "S Hue BPM", NumberFieldType, 0, 255, getSHueBpm, nullptr, setSHueBpm}, - {"sHueMin", "S Hue Min", NumberFieldType, 0, 255, getSHueMin, nullptr, setSHueMin}, - {"sHueMax", "S Hue Max", NumberFieldType, 0, 255, getSHueMax, nullptr, setSHueMax}, + {"sHueBpm", "S Hue BPM", NumberFieldType, 0, 255, getSHueBpm, nullptr, setSHueBpm}, + {"sHueMin", "S Hue Min", NumberFieldType, 0, 255, getSHueMin, nullptr, setSHueMin}, + {"sHueMax", "S Hue Max", NumberFieldType, 0, 255, getSHueMax, nullptr, setSHueMax}, }; -uint8_t fieldCount = ARRAY_SIZE2(fields); +const uint8_t fieldCount = ARRAY_SIZE2(fields); +// TODO: consider using ArduinoJSON ... pre-allocated buffer, simpler usage, tested code + +Field getField(String name) { + return getField(name, fields); +} +String getFieldValue(String name) { + return getFieldValue(name, fields); +} +String setFieldValue(String name, String value) { + return setFieldValue(name, value, fields); +} +String getFieldsJson() { + return getFieldsJson(fields); +} + diff --git a/esp8266-fastled-webserver/GradientPalettes.h b/esp8266-fastled-webserver/GradientPalettes.cpp similarity index 99% rename from esp8266-fastled-webserver/GradientPalettes.h rename to esp8266-fastled-webserver/GradientPalettes.cpp index c9d6eb2b..219c9424 100644 --- a/esp8266-fastled-webserver/GradientPalettes.h +++ b/esp8266-fastled-webserver/GradientPalettes.cpp @@ -1,3 +1,5 @@ +#include "common.h" + // From ColorWavesWithPalettes by Mark Kriegsman: https://gist.github.com/kriegsman/8281905786e8b2632aeb // Gradient Color Palette definitions for 33 different cpt-city color palettes. diff --git a/esp8266-fastled-webserver/Info.h b/esp8266-fastled-webserver/Info.cpp similarity index 99% rename from esp8266-fastled-webserver/Info.h rename to esp8266-fastled-webserver/Info.cpp index 0be3f50c..badab026 100644 --- a/esp8266-fastled-webserver/Info.h +++ b/esp8266-fastled-webserver/Info.cpp @@ -1,3 +1,5 @@ +#include "common.h" + String WiFi_SSID(bool persistent) { struct station_config conf; if(persistent) wifi_station_get_config_default(&conf); diff --git a/esp8266-fastled-webserver/Map.h b/esp8266-fastled-webserver/Map.cpp similarity index 98% rename from esp8266-fastled-webserver/Map.h rename to esp8266-fastled-webserver/Map.cpp index 85690ff7..da95218b 100644 --- a/esp8266-fastled-webserver/Map.h +++ b/esp8266-fastled-webserver/Map.cpp @@ -1,4 +1,6 @@ -#if IS_FIBONACCI || HAS_COORDINATE_MAP +#include "common.h" + +#if HAS_COORDINATE_MAP // IS_FIBONACCI and HAS_POLAR_COORDS each imply HAS_COORDINATE_MAP // Each Fibonacci board must define the following arrays: // @@ -141,41 +143,6 @@ static const uint8_t RADII_SCALE_DIVISOR { 1 }; // radii[] values are already in range [0..255] static const uint8_t RADII_SCALE_MULTIPLIER { 1 }; // radii[] values are already in range [0..255] - // Polar coordinate mapping code for FastLED by Adam Haile, Maniacal Labs: - // http://maniacallabs.com/2015/05/04/review-code-adafruit-dotstar-disk/ - // https://gist.github.com/adammhaile/a769f3ff87ff61f22ace - - #define ringCount 20 // Total Number of Rings. AdaFruit Disk has 10 - #define lastRing (ringCount-1) // for convenience - - //Map rings on disk to indicies. - //Each represents one of the concentric rings. - //TODO: change to structure with min/max (inclusive), to clarify meaning of indices - const uint16_t rings[ringCount][2] { - // { first pixel of the ring, last pixel of the ring } // INCLUSIVE indices - { 0, 3 }, - { 4, 15 }, - { 16, 36 }, - { 37, 65 }, - { 66, 102 }, - { 103, 147 }, - { 148, 200 }, - { 201, 262 }, - { 263, 332 }, - { 333, 410 }, - { 411, 496 }, - { 497, 590 }, - { 591, 692 }, - { 693, 803 }, - { 804, 920 }, - { 921, 1045 }, - { 1046, 1180 }, - { 1181, 1322 }, - { 1323, 1467 }, - { 1468, 1627 }, - }; - - #else #error "Unknown / Unsupported product ... no mappings defined" #endif @@ -276,7 +243,7 @@ void andPixelAR(uint8_t angle, uint8_t dAngle, uint8_t startRadius, uint8_t endR #if HAS_RADIUS_PROXY // antialiasPixelAR() uses angles[] and radiusProxy[] // given an angle and radius (and delta for both), set pixels that fall inside that range, // fading the color from full-color at center, to off (black) at the outer edges. -void antialiasPixelAR(uint8_t angle, uint8_t dAngle, uint8_t startRadius, uint8_t endRadius, CRGB color, CRGB leds[] = leds, int _NUM_PIXELS = NUM_PIXELS) +void antialiasPixelAR(uint8_t angle, uint8_t dAngle, uint8_t startRadius, uint8_t endRadius, CRGB color, CRGB leds[], int _NUM_PIXELS) { // NOTE: // An earlier version of this routine had significant bugs. diff --git a/esp8266-fastled-webserver/Noise.h b/esp8266-fastled-webserver/Noise.cpp similarity index 80% rename from esp8266-fastled-webserver/Noise.h rename to esp8266-fastled-webserver/Noise.cpp index 2457ddbc..69d03772 100644 --- a/esp8266-fastled-webserver/Noise.h +++ b/esp8266-fastled-webserver/Noise.cpp @@ -16,6 +16,47 @@ along with this program. If not, see . */ +#include "common.h" + +#if 0 && defined(PRODUCT_1628_RINGS) + // NOTE: these are entirely unused, and thus commented out entirely. + // however, they are retained in case they would be useful in future. + + // Polar coordinate mapping code for FastLED by Adam Haile, Maniacal Labs: + // http://maniacallabs.com/2015/05/04/review-code-adafruit-dotstar-disk/ + // https://gist.github.com/adammhaile/a769f3ff87ff61f22ace + + const uint8_t ringCount { 20 }; // Total Number of Rings. AdaFruit Disk has 10 + const uint8_t lastRing { ringCount - 1 }; // for convenience + + //Map rings on disk to indicies. + //Each represents one of the concentric rings. + //TODO: change to structure with min/max (inclusive), to clarify meaning of indices + const uint16_t rings[ringCount][2] { + // { first pixel of the ring, last pixel of the ring } // INCLUSIVE indices + { 0, 3 }, + { 4, 15 }, + { 16, 36 }, + { 37, 65 }, + { 66, 102 }, + { 103, 147 }, + { 148, 200 }, + { 201, 262 }, + { 263, 332 }, + { 333, 410 }, + { 411, 496 }, + { 497, 590 }, + { 591, 692 }, + { 693, 802 }, + { 803, 920 }, + { 921, 1045 }, + { 1046, 1180 }, + { 1181, 1322 }, + { 1323, 1467 }, + { 1468, 1627 }, + }; +#endif + // drawNoise() function uses coordsX / coordsY #if HAS_COORDINATE_MAP @@ -47,6 +88,9 @@ static uint16_t noisescale = 1; // scale is set dynamically once we've started u static uint8_t colorLoop = 0; + + + static const CRGBPalette16 blackAndWhiteStripedPalette { CRGB::White, CRGB::Black, CRGB::Black, CRGB::Black, CRGB::White, CRGB::Black, CRGB::Black, CRGB::Black, @@ -68,7 +112,6 @@ static const CRGBPalette16 blackAndBlueStripedPalette { // // Additionally, you can manually define your own color palettes, or you can write // code that creates color palettes on the fly. - CRGB noiseXYZ(CRGBPalette16 palette, uint8_t hueReduce, int x, int y, int z) { uint8_t data = inoise8(x, y, z); @@ -103,46 +146,24 @@ void drawNoise(CRGBPalette16 palette, uint8_t hueReduce = 0) } #if HAS_POLAR_COORDS // change to "HAS_CONCENTRIC_RINGS" ? - -// TODO: The calculations for x/y in drawPolarNoise() depend only upon constant array values. -// Pre-calculate those, and define a proxy for noise() routine that points to this -// pre-calculated array. Then, the code is identical for all noise() functions, differing -// only in the X/Y arrays and palette used. - -// drawPolarNoise() uses rings[] +// drawPolarNoise() uses angles[] and rings[][] (may move to using radii[]) void drawPolarNoise(CRGBPalette16 palette, uint8_t hueReduce = 0) { - for (uint8_t ringIndex = 0; ringIndex < ringCount; ringIndex++) { // y == proxy for radius - uint16_t ringStart = rings[ringIndex][0]; - uint16_t ringEnd = rings[ringIndex][1]; - - for (uint16_t i = ringStart; i <= ringEnd; i++) { // x - uint8_t x = (i - ringStart) * (256 / (ringEnd - ringStart)); // proxy for angle[]? - uint8_t y = ringIndex * (128 / ringCount); // 128 / 20 == 6 ... or about half the total range ... could use (radius[] / 2)? - - int xoffset = noisescale * x; - int yoffset = noisescale * y; - - leds[i] = noiseXYZ(palette, hueReduce, x + xoffset + noisex, y + yoffset + noisey, noisez); - } + for (uint16_t i = 0; i < NUM_PIXELS; i++) { + uint8_t x = angles[i]; + uint8_t y = radii[i] / 2u; // divide by 2 to change range of values from [0..255] to [0..127] + + int xoffset = noisescale * x; + int yoffset = noisescale * y; + leds[i] = noiseXYZ(palette, hueReduce, x + xoffset + noisex, y + yoffset + noisey, noisez); } - // for (uint8_t ringIndex = 1; ringIndex < ringCount; ringIndex++) { - // uint16_t ringStart = rings[ringIndex][0]; - // uint16_t ringEnd = rings[ringIndex][1]; - // // blend the first pixel in the ring into the last - // nblend(leds[ringStart], leds[ringEnd], 192); - // nblend(leds[ringStart + 1], leds[ringEnd - 1], 128); - // nblend(leds[ringStart + 2], leds[ringEnd - 2], 64); - // } - noisex += noisespeedx; noisey += noisespeedy; noisez += noisespeedz; } - #endif // HAS_POLAR_COORDS -#if HAS_POLAR_COORDS // uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // gradientPalettePolarNoise() uses drawPolarNoise() // TODO: Check if gradientPalettePolarNoise() is equivalent to angleGradientPalette()? void gradientPalettePolarNoise() { noisespeedx = 4; @@ -153,7 +174,7 @@ void gradientPalettePolarNoise() { drawPolarNoise(gCurrentPalette); } #endif -#if HAS_POLAR_COORDS // palettePolarNoise() uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // palettePolarNoise() uses drawPolarNoise() void palettePolarNoise() { noisespeedx = 9; noisespeedy = 0; @@ -173,7 +194,7 @@ void rainbowNoise() { drawNoise(RainbowColors_p); } -#if HAS_POLAR_COORDS // rainbowPolarNoise() uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // rainbowPolarNoise() uses drawPolarNoise() void rainbowPolarNoise() { noisespeedx = 0; noisespeedy = 2; @@ -193,7 +214,7 @@ void rainbowStripeNoise() { drawNoise(RainbowStripeColors_p); } -#if HAS_POLAR_COORDS // rainbowStripePolarNoise() uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // rainbowStripePolarNoise() uses drawPolarNoise() void rainbowStripePolarNoise() { noisespeedx = 0; noisespeedy = 2; @@ -213,7 +234,7 @@ void partyNoise() { drawNoise(PartyColors_p); } -#if HAS_POLAR_COORDS // partyPolarNoise() uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // partyPolarNoise() uses drawPolarNoise() void partyPolarNoise() { noisespeedx = 9; noisespeedy = 0; @@ -233,7 +254,7 @@ void forestNoise() { drawNoise(ForestColors_p); } -#if HAS_POLAR_COORDS // forestPolarNoise() uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // forestPolarNoise() uses drawPolarNoise() void forestPolarNoise() { noisespeedx = 9; noisespeedy = 0; @@ -253,7 +274,7 @@ void cloudNoise() { drawNoise(CloudColors_p); } -#if HAS_POLAR_COORDS // cloudPolarNoise() uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // cloudPolarNoise() uses drawPolarNoise() void cloudPolarNoise() { noisespeedx = 2; noisespeedy = 0; @@ -273,7 +294,7 @@ void fireNoise() { drawNoise(HeatColors_p, 60); } -#if HAS_POLAR_COORDS // firePolarNoise() uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // firePolarNoise() uses drawPolarNoise() void firePolarNoise() { // noisespeedx = 0; // 24; // noisespeedy = -24; @@ -298,7 +319,7 @@ void fireNoise2() { drawNoise(HeatColors_p); } -#if HAS_POLAR_COORDS // firePolarNoise2() uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // firePolarNoise2() uses drawPolarNoise() void firePolarNoise2() { // noisespeedx = 0; // noisespeedy = -8; @@ -323,7 +344,7 @@ void lavaNoise() { drawNoise(LavaColors_p); } -#if HAS_POLAR_COORDS // lavaPolarNoise() uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // lavaPolarNoise() uses drawPolarNoise() void lavaPolarNoise() { noisespeedx = 0; noisespeedy = -1; @@ -343,7 +364,7 @@ void oceanNoise() { drawNoise(OceanColors_p); } -#if HAS_POLAR_COORDS // oceanPolarNoise() uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // oceanPolarNoise() uses drawPolarNoise() void oceanPolarNoise() { noisespeedx = -1; // beatsin8(6, 0, 2) - 1; noisespeedy = 0; @@ -363,7 +384,7 @@ void blackAndWhiteNoise() { drawNoise(blackAndWhiteStripedPalette); } -#if HAS_POLAR_COORDS // blackAndWhitePolarNoise() uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // blackAndWhitePolarNoise() uses drawPolarNoise() void blackAndWhitePolarNoise() { noisespeedx = -4; // beatsin8(8, 0, 9) - 4; noisespeedy = 0; @@ -383,7 +404,7 @@ void blackAndBlueNoise() { drawNoise(blackAndBlueStripedPalette); } -#if HAS_POLAR_COORDS // blackAndBluePolarNoise() uses drawPolarNoise(), which uses rings[] +#if HAS_POLAR_COORDS // blackAndBluePolarNoise() uses drawPolarNoise() void blackAndBluePolarNoise() { noisespeedx = 0; noisespeedy = -8; // beatsin8(8, 0, 16) - 8; diff --git a/esp8266-fastled-webserver/Pacifica.h b/esp8266-fastled-webserver/Pacifica.cpp similarity index 99% rename from esp8266-fastled-webserver/Pacifica.h rename to esp8266-fastled-webserver/Pacifica.cpp index 3ed81dc5..1356950a 100644 --- a/esp8266-fastled-webserver/Pacifica.h +++ b/esp8266-fastled-webserver/Pacifica.cpp @@ -1,3 +1,4 @@ +#include "common.h" // // "Pacifica" // Gentle, blue-green ocean waves. diff --git a/esp8266-fastled-webserver/Ping.h b/esp8266-fastled-webserver/Ping.cpp similarity index 99% rename from esp8266-fastled-webserver/Ping.h rename to esp8266-fastled-webserver/Ping.cpp index 83fd2ef3..d1adce34 100644 --- a/esp8266-fastled-webserver/Ping.h +++ b/esp8266-fastled-webserver/Ping.cpp @@ -31,6 +31,7 @@ // this data to any 3rd parties, ever. // This was a feature I needed for my own devices, of which there are dozens. :) +#include "common.h" const bool discovery = false; const String serverName = "https://ping.evilgeniuslabs.org"; // address of server to ping diff --git a/esp8266-fastled-webserver/PridePlayground.h b/esp8266-fastled-webserver/PridePlayground.cpp similarity index 99% rename from esp8266-fastled-webserver/PridePlayground.h rename to esp8266-fastled-webserver/PridePlayground.cpp index c58f67e7..2831bf76 100644 --- a/esp8266-fastled-webserver/PridePlayground.h +++ b/esp8266-fastled-webserver/PridePlayground.cpp @@ -1,3 +1,5 @@ +#include "common.h" + // Pride2015 by Mark Kriegsman: https://gist.github.com/kriegsman/964de772d64c502760e5 // This function draws rainbows with an ever-changing, // widely-varying set of parameters. diff --git a/esp8266-fastled-webserver/TwinkleFOX.h b/esp8266-fastled-webserver/TwinkleFOX.cpp similarity index 95% rename from esp8266-fastled-webserver/TwinkleFOX.h rename to esp8266-fastled-webserver/TwinkleFOX.cpp index 26958890..7a486d2a 100644 --- a/esp8266-fastled-webserver/TwinkleFOX.h +++ b/esp8266-fastled-webserver/TwinkleFOX.cpp @@ -59,6 +59,7 @@ // smoothly at over 50 updates per seond. // // -Mark Kriegsman, December 2015 +#include "common.h" // Overall twinkle speed. // 0 (VERY slow) to 8 (VERY fast). @@ -230,7 +231,7 @@ void drawTwinkles() // A mostly red palette with green accents and white trim. // "CRGB::Gray" is used as white to keep the brightness more uniform. -const TProgmemRGBPalette16 RedGreenWhite_p FL_PROGMEM = +FL_ALIGN_PROGMEM const TProgmemRGBPalette16 RedGreenWhite_p FL_PROGMEM = { CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray, @@ -239,7 +240,7 @@ const TProgmemRGBPalette16 RedGreenWhite_p FL_PROGMEM = // A mostly (dark) green palette with red berries. #define Holly_Green 0x00580c #define Holly_Red 0xB00402 -const TProgmemRGBPalette16 Holly_p FL_PROGMEM = +FL_ALIGN_PROGMEM const TProgmemRGBPalette16 Holly_p FL_PROGMEM = { Holly_Green, Holly_Green, Holly_Green, Holly_Green, Holly_Green, Holly_Green, Holly_Green, Holly_Green, Holly_Green, Holly_Green, Holly_Green, Holly_Green, @@ -248,7 +249,7 @@ const TProgmemRGBPalette16 Holly_p FL_PROGMEM = // A red and white striped palette // "CRGB::Gray" is used as white to keep the brightness more uniform. -const TProgmemRGBPalette16 RedWhite_p FL_PROGMEM = +FL_ALIGN_PROGMEM const TProgmemRGBPalette16 RedWhite_p FL_PROGMEM = { CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray, CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray, CRGB::Red, CRGB::Red, CRGB::Gray, CRGB::Gray, @@ -256,7 +257,7 @@ const TProgmemRGBPalette16 RedWhite_p FL_PROGMEM = // A mostly blue palette with white accents. // "CRGB::Gray" is used as white to keep the brightness more uniform. -const TProgmemRGBPalette16 BlueWhite_p FL_PROGMEM = +FL_ALIGN_PROGMEM const TProgmemRGBPalette16 BlueWhite_p FL_PROGMEM = { CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, CRGB::Blue, @@ -265,14 +266,14 @@ const TProgmemRGBPalette16 BlueWhite_p FL_PROGMEM = // A pure "fairy light" palette with some brightness variations #define HALFFAIRY ((CRGB::FairyLight & 0xFEFEFE) / 2) #define QUARTERFAIRY ((CRGB::FairyLight & 0xFCFCFC) / 4) -const TProgmemRGBPalette16 FairyLight_p FL_PROGMEM = +FL_ALIGN_PROGMEM const TProgmemRGBPalette16 FairyLight_p FL_PROGMEM = { CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, HALFFAIRY, HALFFAIRY, CRGB::FairyLight, CRGB::FairyLight, QUARTERFAIRY, QUARTERFAIRY, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight, CRGB::FairyLight }; // A palette of soft snowflakes with the occasional bright one -const TProgmemRGBPalette16 Snow_p FL_PROGMEM = +FL_ALIGN_PROGMEM const TProgmemRGBPalette16 Snow_p FL_PROGMEM = { 0x304048, 0x304048, 0x304048, 0x304048, 0x304048, 0x304048, 0x304048, 0x304048, 0x304048, 0x304048, 0x304048, 0x304048, @@ -285,7 +286,7 @@ const TProgmemRGBPalette16 Snow_p FL_PROGMEM = #define C9_Green 0x046002 #define C9_Blue 0x070758 #define C9_White 0x606820 -const TProgmemRGBPalette16 RetroC9_p FL_PROGMEM = +FL_ALIGN_PROGMEM const TProgmemRGBPalette16 RetroC9_p FL_PROGMEM = { C9_Red, C9_Orange, C9_Red, C9_Orange, C9_Orange, C9_Red, C9_Orange, C9_Red, C9_Green, C9_Green, C9_Green, C9_Green, @@ -297,7 +298,7 @@ const TProgmemRGBPalette16 RetroC9_p FL_PROGMEM = #define Ice_Blue1 0x0C1040 #define Ice_Blue2 0x182080 #define Ice_Blue3 0x5080C0 -const TProgmemRGBPalette16 Ice_p FL_PROGMEM = +FL_ALIGN_PROGMEM const TProgmemRGBPalette16 Ice_p FL_PROGMEM = { Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1, Ice_Blue1, diff --git a/esp8266-fastled-webserver/Twinkles.h b/esp8266-fastled-webserver/Twinkles.cpp similarity index 99% rename from esp8266-fastled-webserver/Twinkles.h rename to esp8266-fastled-webserver/Twinkles.cpp index 57efcb74..71cb9f21 100644 --- a/esp8266-fastled-webserver/Twinkles.h +++ b/esp8266-fastled-webserver/Twinkles.cpp @@ -1,5 +1,7 @@ // based on ColorTwinkles by Mark Kriegsman: https://gist.github.com/kriegsman/5408ecd397744ba0393e +#include "common.h" + #define STARTING_BRIGHTNESS 64 #define FADE_IN_SPEED 32 #define FADE_OUT_SPEED 20 diff --git a/esp8266-fastled-webserver/Commands.h b/esp8266-fastled-webserver/commands.cpp similarity index 52% rename from esp8266-fastled-webserver/Commands.h rename to esp8266-fastled-webserver/commands.cpp index bbb7a0f4..ea054190 100644 --- a/esp8266-fastled-webserver/Commands.h +++ b/esp8266-fastled-webserver/commands.cpp @@ -16,6 +16,12 @@ * along with this program. If not, see . */ +#include "common.h" + +#if defined(ENABLE_IR) + +IRrecv irReceiver(RECV_PIN); + enum class InputCommand { None, Up, @@ -75,98 +81,101 @@ enum class InputCommand { LightBlue, }; -// IR Raw Key Codes for SparkFun remote -#define IRCODE_SPARKFUN_POWER 0x10EFD827 // 284153895 -#define IRCODE_SPARKFUN_A 0x10EFF807 // -#define IRCODE_SPARKFUN_B 0x10EF7887 -#define IRCODE_SPARKFUN_C 0x10EF58A7 -#define IRCODE_SPARKFUN_UP 0x10EFA05F // 284139615 -#define IRCODE_SPARKFUN_LEFT 0x10EF10EF -#define IRCODE_SPARKFUN_SELECT 0x10EF20DF -#define IRCODE_SPARKFUN_RIGHT 0x10EF807F -#define IRCODE_SPARKFUN_DOWN 0x10EF00FF -#define IRCODE_SPARKFUN_HELD 0xFFFFFFFF - -// IR Raw Key Codes for Adafruit remote -#define IRCODE_ADAFRUIT_HELD 0x7FFFFFFF // 4294967295 -#define IRCODE_ADAFRUIT_VOLUME_UP 0x00FD40BF // 16597183 -#define IRCODE_ADAFRUIT_PLAY_PAUSE 0x00FD807F // 16613503 -#define IRCODE_ADAFRUIT_VOLUME_DOWN 0x00FD00FF // 16580863 -#define IRCODE_ADAFRUIT_SETUP 0x00FD20DF // 16589023 -#define IRCODE_ADAFRUIT_UP 0x00FDA05F // 16621663 -#define IRCODE_ADAFRUIT_STOP_MODE 0x00FD609F // 16605343 -#define IRCODE_ADAFRUIT_LEFT 0x00FD10EF // 16584943 -#define IRCODE_ADAFRUIT_ENTER_SAVE 0x00FD906F // 16617583 -#define IRCODE_ADAFRUIT_RIGHT 0x00FD50AF // 16601263 -#define IRCODE_ADAFRUIT_0_10_PLUS 0x00FD30CF // 16593103 -#define IRCODE_ADAFRUIT_DOWN 0x00FDB04F // 16625743 -#define IRCODE_ADAFRUIT_BACK 0x00FD708F // 16609423 -#define IRCODE_ADAFRUIT_1 0x00FD08F7 // 16582903 -#define IRCODE_ADAFRUIT_2 0x00FD8877 // 16615543 -#define IRCODE_ADAFRUIT_3 0x00FD48B7 // 16599223 -#define IRCODE_ADAFRUIT_4 0x00FD28D7 // 16591063 -#define IRCODE_ADAFRUIT_5 0x00FDA857 // 16623703 -#define IRCODE_ADAFRUIT_6 0x00FD6897 // 16607383 -#define IRCODE_ADAFRUIT_7 0x00FD18E7 // 16586983 -#define IRCODE_ADAFRUIT_8 0x00FD9867 // 16619623 -#define IRCODE_ADAFRUIT_9 0x00FD58A7 // 16603303 - -// IR Raw Key Codes for eTopxizu 44Key IR Remote Controller for 5050 3528 RGB LED Light Strip -#define IRCODE_ETOPXIZU_HELD 0x7FFFFFFF // 4294967295 -#define IRCODE_ETOPXIZU_POWER 16712445 -#define IRCODE_ETOPXIZU_PLAY_PAUSE 16745085 -#define IRCODE_ETOPXIZU_BRIGHTNESS_UP 16726725 -#define IRCODE_ETOPXIZU_BRIGHTNESS_DOWN 16759365 - -#define IRCODE_ETOPXIZU_DIY1 16724175 -#define IRCODE_ETOPXIZU_DIY2 16756815 -#define IRCODE_ETOPXIZU_DIY3 16740495 -#define IRCODE_ETOPXIZU_DIY4 16716015 -#define IRCODE_ETOPXIZU_DIY5 16748655 -#define IRCODE_ETOPXIZU_DIY6 16732335 - -#define IRCODE_ETOPXIZU_JUMP3 16720095 -#define IRCODE_ETOPXIZU_JUMP7 16752735 -#define IRCODE_ETOPXIZU_FADE3 16736415 -#define IRCODE_ETOPXIZU_FADE7 16769055 -#define IRCODE_ETOPXIZU_FLASH 16764975 -#define IRCODE_ETOPXIZU_AUTO 16773135 - -#define IRCODE_ETOPXIZU_QUICK 16771095 -#define IRCODE_ETOPXIZU_SLOW 16762935 - -#define IRCODE_ETOPXIZU_RED_UP 16722135 -#define IRCODE_ETOPXIZU_RED_DOWN 16713975 - -#define IRCODE_ETOPXIZU_GREEN_UP 16754775 -#define IRCODE_ETOPXIZU_GREEN_DOWN 16746615 - -#define IRCODE_ETOPXIZU_BLUE_UP 16738455 -#define IRCODE_ETOPXIZU_BLUE_DOWN 16730295 - -#define IRCODE_ETOPXIZU_RED 16718565 -#define IRCODE_ETOPXIZU_RED_ORANGE 16722645 -#define IRCODE_ETOPXIZU_ORANGE 16714485 -#define IRCODE_ETOPXIZU_YELLOW_ORANGE 16726215 -#define IRCODE_ETOPXIZU_YELLOW 16718055 - -#define IRCODE_ETOPXIZU_GREEN 16751205 -#define IRCODE_ETOPXIZU_LIME 16755285 -#define IRCODE_ETOPXIZU_AQUA 16747125 -#define IRCODE_ETOPXIZU_TEAL 16758855 -#define IRCODE_ETOPXIZU_NAVY 16750695 - -#define IRCODE_ETOPXIZU_BLUE 16753245 -#define IRCODE_ETOPXIZU_ROYAL_BLUE 16749165 -#define IRCODE_ETOPXIZU_PURPLE 16757325 -#define IRCODE_ETOPXIZU_INDIGO 16742535 -#define IRCODE_ETOPXIZU_MAGENTA 16734375 - -#define IRCODE_ETOPXIZU_WHITE 16720605 -#define IRCODE_ETOPXIZU_PINK 16716525 -#define IRCODE_ETOPXIZU_LIGHT_PINK 16724685 -#define IRCODE_ETOPXIZU_BABY_BLUE 16775175 -#define IRCODE_ETOPXIZU_LIGHT_BLUE 16767015 +#if 1 // collapse IR codes + // IR Raw Key Codes for SparkFun remote + #define IRCODE_SPARKFUN_POWER 0x10EFD827 // 284153895 + #define IRCODE_SPARKFUN_A 0x10EFF807 // + #define IRCODE_SPARKFUN_B 0x10EF7887 + #define IRCODE_SPARKFUN_C 0x10EF58A7 + #define IRCODE_SPARKFUN_UP 0x10EFA05F // 284139615 + #define IRCODE_SPARKFUN_LEFT 0x10EF10EF + #define IRCODE_SPARKFUN_SELECT 0x10EF20DF + #define IRCODE_SPARKFUN_RIGHT 0x10EF807F + #define IRCODE_SPARKFUN_DOWN 0x10EF00FF + #define IRCODE_SPARKFUN_HELD 0xFFFFFFFF + + // IR Raw Key Codes for Adafruit remote + #define IRCODE_ADAFRUIT_HELD 0x7FFFFFFF // 4294967295 + #define IRCODE_ADAFRUIT_VOLUME_UP 0x00FD40BF // 16597183 + #define IRCODE_ADAFRUIT_PLAY_PAUSE 0x00FD807F // 16613503 + #define IRCODE_ADAFRUIT_VOLUME_DOWN 0x00FD00FF // 16580863 + #define IRCODE_ADAFRUIT_SETUP 0x00FD20DF // 16589023 + #define IRCODE_ADAFRUIT_UP 0x00FDA05F // 16621663 + #define IRCODE_ADAFRUIT_STOP_MODE 0x00FD609F // 16605343 + #define IRCODE_ADAFRUIT_LEFT 0x00FD10EF // 16584943 + #define IRCODE_ADAFRUIT_ENTER_SAVE 0x00FD906F // 16617583 + #define IRCODE_ADAFRUIT_RIGHT 0x00FD50AF // 16601263 + #define IRCODE_ADAFRUIT_0_10_PLUS 0x00FD30CF // 16593103 + #define IRCODE_ADAFRUIT_DOWN 0x00FDB04F // 16625743 + #define IRCODE_ADAFRUIT_BACK 0x00FD708F // 16609423 + #define IRCODE_ADAFRUIT_1 0x00FD08F7 // 16582903 + #define IRCODE_ADAFRUIT_2 0x00FD8877 // 16615543 + #define IRCODE_ADAFRUIT_3 0x00FD48B7 // 16599223 + #define IRCODE_ADAFRUIT_4 0x00FD28D7 // 16591063 + #define IRCODE_ADAFRUIT_5 0x00FDA857 // 16623703 + #define IRCODE_ADAFRUIT_6 0x00FD6897 // 16607383 + #define IRCODE_ADAFRUIT_7 0x00FD18E7 // 16586983 + #define IRCODE_ADAFRUIT_8 0x00FD9867 // 16619623 + #define IRCODE_ADAFRUIT_9 0x00FD58A7 // 16603303 + + // IR Raw Key Codes for eTopxizu 44Key IR Remote Controller for 5050 3528 RGB LED Light Strip + #define IRCODE_ETOPXIZU_HELD 0x7FFFFFFF // 4294967295 + #define IRCODE_ETOPXIZU_POWER 16712445 + #define IRCODE_ETOPXIZU_PLAY_PAUSE 16745085 + #define IRCODE_ETOPXIZU_BRIGHTNESS_UP 16726725 + #define IRCODE_ETOPXIZU_BRIGHTNESS_DOWN 16759365 + + #define IRCODE_ETOPXIZU_DIY1 16724175 + #define IRCODE_ETOPXIZU_DIY2 16756815 + #define IRCODE_ETOPXIZU_DIY3 16740495 + #define IRCODE_ETOPXIZU_DIY4 16716015 + #define IRCODE_ETOPXIZU_DIY5 16748655 + #define IRCODE_ETOPXIZU_DIY6 16732335 + + #define IRCODE_ETOPXIZU_JUMP3 16720095 + #define IRCODE_ETOPXIZU_JUMP7 16752735 + #define IRCODE_ETOPXIZU_FADE3 16736415 + #define IRCODE_ETOPXIZU_FADE7 16769055 + #define IRCODE_ETOPXIZU_FLASH 16764975 + #define IRCODE_ETOPXIZU_AUTO 16773135 + + #define IRCODE_ETOPXIZU_QUICK 16771095 + #define IRCODE_ETOPXIZU_SLOW 16762935 + + #define IRCODE_ETOPXIZU_RED_UP 16722135 + #define IRCODE_ETOPXIZU_RED_DOWN 16713975 + + #define IRCODE_ETOPXIZU_GREEN_UP 16754775 + #define IRCODE_ETOPXIZU_GREEN_DOWN 16746615 + + #define IRCODE_ETOPXIZU_BLUE_UP 16738455 + #define IRCODE_ETOPXIZU_BLUE_DOWN 16730295 + + #define IRCODE_ETOPXIZU_RED 16718565 + #define IRCODE_ETOPXIZU_RED_ORANGE 16722645 + #define IRCODE_ETOPXIZU_ORANGE 16714485 + #define IRCODE_ETOPXIZU_YELLOW_ORANGE 16726215 + #define IRCODE_ETOPXIZU_YELLOW 16718055 + + #define IRCODE_ETOPXIZU_GREEN 16751205 + #define IRCODE_ETOPXIZU_LIME 16755285 + #define IRCODE_ETOPXIZU_AQUA 16747125 + #define IRCODE_ETOPXIZU_TEAL 16758855 + #define IRCODE_ETOPXIZU_NAVY 16750695 + + #define IRCODE_ETOPXIZU_BLUE 16753245 + #define IRCODE_ETOPXIZU_ROYAL_BLUE 16749165 + #define IRCODE_ETOPXIZU_PURPLE 16757325 + #define IRCODE_ETOPXIZU_INDIGO 16742535 + #define IRCODE_ETOPXIZU_MAGENTA 16734375 + + #define IRCODE_ETOPXIZU_WHITE 16720605 + #define IRCODE_ETOPXIZU_PINK 16716525 + #define IRCODE_ETOPXIZU_LIGHT_PINK 16724685 + #define IRCODE_ETOPXIZU_BABY_BLUE 16775175 + #define IRCODE_ETOPXIZU_LIGHT_BLUE 16767015 +#endif + bool sparkfunRemoteEnabled = true; bool adafruitRemoteEnabled = true; @@ -216,7 +225,7 @@ unsigned long readIRCode() { unsigned long lastIrCode = 0; unsigned int holdStartTime = 0; -unsigned int defaultHoldDelay = 500; +// unsigned int defaultHoldDelay = 500; bool isHolding = false; unsigned int zeroStartTime = 0; @@ -287,22 +296,6 @@ unsigned long readIRCode(unsigned int holdDelay) { return 0; } -void heldButtonHasBeenHandled() { - lastIrCode = 0; - isHolding = false; - holdStartTime = 0; -} - -unsigned long waitForIRCode() { - - unsigned long irCode = readIRCode(); - while ((irCode == 0) || (irCode == 0xFFFFFFFF)) { - delay(200); - irCode = readIRCode(); - } - return irCode; -} - InputCommand getCommand(unsigned long input) { if (adafruitRemoteEnabled) { switch (input) { @@ -482,3 +475,212 @@ InputCommand readCommand() { InputCommand readCommand(unsigned int holdDelay) { return getCommand(readIRCode(holdDelay)); } + +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; + } + } +} + +#endif diff --git a/esp8266-fastled-webserver/common.h b/esp8266-fastled-webserver/common.h index 04b8bb25..0bcf7473 100644 --- a/esp8266-fastled-webserver/common.h +++ b/esp8266-fastled-webserver/common.h @@ -19,33 +19,105 @@ #if !defined(ESP8266_FASTLED_WEBSERVER_COMMON_H) #define ESP8266_FASTLED_WEBSERVER_COMMON_H -#include "./include/simplehacks/static_eval.h" -#include "./include/simplehacks/constexpr_strlen.h" -#include "./include/simplehacks/array_size2.h" +#include "Arduino.h" -#include "config.h" // must be included before FastLED.h +// config.h must be included before FastLED, as it may define FastLED options +// such as whether to disable interrupts, etc. +// config.h defines pre-processor symbols, but does not itself define functions, structs, etc. +#include "config.h" -#define FASTLED_INTERNAL // no other way to suppress build warnings -#include -FASTLED_USING_NAMESPACE +#if 1 // external libraries + #define FASTLED_INTERNAL // no other way to suppress build warnings + #include + FASTLED_USING_NAMESPACE -extern "C" { -#include "user_interface.h" + extern "C" { + #include "user_interface.h" + } + + #include + #define MYFS LittleFS + + #include + #include + #include + #include + #include + #include + #include + //#include + #include + #include // https://github.com/tzapu/WiFiManager/tree/development + + + #include "./include/simplehacks/static_eval.h" + #include "./include/simplehacks/constexpr_strlen.h" + #include "./include/simplehacks/array_size2.h" +#endif // 1 + +void dimAll(byte value); +// info.cpp +String WiFi_SSID(bool persistent); +String getInfoJson(); + + +// Ugly macro-like constexpr, used for FastLED template arguments +template +constexpr int LedOffset() { + static_assert(ONE_BASED_OUTPUT_CHANNEL <= PARALLEL_OUTPUT_CHANNELS, ""); + static_assert(ONE_BASED_OUTPUT_CHANNEL >= 1, ""); + return 0 // this would be much simpler with C++14 + #if PARALLEL_OUTPUT_CHANNELS >= 2 + + ((ONE_BASED_OUTPUT_CHANNEL >= 2) ? PIXELS_ON_DATA_PIN_1 : 0) + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 3 + + ((ONE_BASED_OUTPUT_CHANNEL >= 3) ? PIXELS_ON_DATA_PIN_2 : 0) + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 4 + + ((ONE_BASED_OUTPUT_CHANNEL >= 4) ? PIXELS_ON_DATA_PIN_3 : 0) + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 5 + + ((ONE_BASED_OUTPUT_CHANNEL >= 5) ? PIXELS_ON_DATA_PIN_4 : 0) + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 6 + + ((ONE_BASED_OUTPUT_CHANNEL >= 6) ? PIXELS_ON_DATA_PIN_5 : 0) + #endif + ; +} +template +constexpr int LedCount() { + static_assert(ONE_BASED_OUTPUT_CHANNEL <= PARALLEL_OUTPUT_CHANNELS, ""); + static_assert(ONE_BASED_OUTPUT_CHANNEL >= 1, ""); + #if PARALLEL_OUTPUT_CHANNELS == 1 + return NUM_PIXELS; + #else + return // this would be much simpler with C++14 + #if PARALLEL_OUTPUT_CHANNELS >= 6 + (ONE_BASED_OUTPUT_CHANNEL == 6) ? PIXELS_ON_DATA_PIN_6 : + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 5 + (ONE_BASED_OUTPUT_CHANNEL == 5) ? PIXELS_ON_DATA_PIN_5 : + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 4 + (ONE_BASED_OUTPUT_CHANNEL == 4) ? PIXELS_ON_DATA_PIN_4 : + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 3 + (ONE_BASED_OUTPUT_CHANNEL == 3) ? PIXELS_ON_DATA_PIN_3 : + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 2 + (ONE_BASED_OUTPUT_CHANNEL == 2) ? PIXELS_ON_DATA_PIN_2 : + #endif + #if PARALLEL_OUTPUT_CHANNELS >= 1 + (ONE_BASED_OUTPUT_CHANNEL == 1) ? PIXELS_ON_DATA_PIN_1 : + #endif + 0; + #endif } -#include -#define MYFS LittleFS +void writeAndCommitSettings(); +void broadcastInt(String name, uint8_t value); +void broadcastString(String name, String value); -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include // https://github.com/tzapu/WiFiManager/tree/development #if defined(ESP32) || defined(ESP8266) // Optional: (LGPL) https://github.com/sinricpro/ESPTrueRandom.git#ed198f459da6d7af65dd13317a4fdc97b23991b4 @@ -57,24 +129,80 @@ extern "C" { #error "Currently only ESP32 and ESP8266 are supported" #endif -#if defined(ENABLE_IR) - #include - #include "commands.h" -#endif + +// Structures +typedef void (*Pattern)(); +typedef Pattern PatternList[]; +typedef struct { + Pattern pattern; + String name; +} PatternAndName; + +typedef struct { + CRGBPalette16 palette; + String name; +} PaletteAndName; + // forward-declarations -// Only list those variables that are needed by the local -// project "header" files (the ones that are actually C++ files) + +// TODO: cleanup to declare minimum necessary variables +// extern const uint8_t brightnessCount; +extern const uint8_t brightnessMap[]; +extern uint8_t brightnessIndex; +extern uint8_t currentPatternIndex; +extern const uint8_t patternCount; +extern const PatternAndName patterns[]; + +extern uint8_t currentPaletteIndex; +extern uint8_t autoplay; +extern uint8_t autoplayDuration; +extern uint8_t showClock; +extern uint8_t clockBackgroundFade; +extern CRGB solidColor; +extern uint8_t cooling; +extern uint8_t sparking; +extern uint8_t speed; +extern uint8_t twinkleSpeed; +extern uint8_t twinkleDensity; +extern uint8_t coolLikeIncandescent; +extern uint8_t saturationBpm; +extern uint8_t saturationMin; +extern uint8_t saturationMax; +extern uint8_t brightDepthBpm; +extern uint8_t brightDepthMin; +extern uint8_t brightDepthMax; +extern uint8_t brightThetaIncBpm; +extern uint8_t brightThetaIncMin; +extern uint8_t brightThetaIncMax; +extern uint8_t msMultiplierBpm; +extern uint8_t msMultiplierMin; +extern uint8_t msMultiplierMax; +extern uint8_t hueIncBpm; +extern uint8_t hueIncMin; +extern uint8_t hueIncMax; +extern uint8_t sHueBpm; +extern uint8_t sHueMin; +extern uint8_t sHueMax; + + + extern const TProgmemRGBGradientPalettePtr gGradientPalettes[]; extern const uint8_t gGradientPaletteCount; extern const CRGBPalette16 palettes[]; extern const uint8_t paletteCount; extern const String paletteNames[]; +extern CRGBPalette16 gCurrentPalette; +extern CRGBPalette16 gTargetPalette; +extern uint8_t gCurrentPaletteNumber; + extern WiFiManager wifiManager; extern ESP8266WebServer webServer; +extern NTPClient timeClient; extern String nameString; +extern CRGB leds[NUM_PIXELS]; #if IS_FIBONACCI // actual data in map.h #if NUM_PIXELS > 256 // when more than 256 pixels, cannot store index in uint8_t.... @@ -94,33 +222,114 @@ extern String nameString; extern const uint8_t angles [NUM_PIXELS]; #endif -// Structures -typedef void (*Pattern)(); -typedef Pattern PatternList[]; -typedef struct { - Pattern pattern; - String name; -} PatternAndName; -typedef PatternAndName PatternAndNameList[]; +#if HAS_POLAR_COORDS + extern const uint8_t radii[NUM_PIXELS]; // needed in noise.cpp +#endif -typedef struct { - CRGBPalette16 palette; - String name; -} PaletteAndName; -typedef PaletteAndName PaletteAndNameList[]; +#include "include/GradientPalettes.hpp" +#include "include/Fields.hpp" +#include "include/FSBrowser.hpp" +// IR (commands.cpp) +#if defined(ENABLE_IR) + #include + extern IRrecv irReceiver; + void handleIrInput(); +#else + inline void handleIrInput() {} +#endif +// ping.cpp +void checkPingTimer(); -// Function prototypes +// effects +// twinkles.cpp +void cloudTwinkles(); +void rainbowTwinkles(); +void snowTwinkles(); +void incandescentTwinkles(); +// twinkleFox.cpp +void redGreenWhiteTwinkles(); +void hollyTwinkles(); +void redWhiteTwinkles(); +void blueWhiteTwinkles(); +void fairyLightTwinkles(); +void snow2Twinkles(); +void iceTwinkles(); +void retroC9Twinkles(); +void partyTwinkles(); +void forestTwinkles(); +void lavaTwinkles(); +void fireTwinkles(); +void cloud2Twinkles(); +void oceanTwinkles(); +// map.h -- only when product defines HAS_COORDINATE_MAP to be true +#if HAS_COORDINATE_MAP +void anglePalette(); +void xPalette(); +void yPalette(); +void xyPalette(); +void xGradientPalette(); +void yGradientPalette(); +void xyGradientPalette(); +void radarSweepPalette(); +void radiusPalette(); +void angleGradientPalette(); +void radiusGradientPalette(); +#endif +// map.h -- only when product defines IS_FIBONACCI to be true +#if IS_FIBONACCI +void drawAnalogClock(); +void drawSpiralAnalogClock13(); +void drawSpiralAnalogClock21(); +void drawSpiralAnalogClock34(); +void drawSpiralAnalogClock55(); +void drawSpiralAnalogClock89(); +void drawSpiralAnalogClock21and34(); +void drawSpiralAnalogClock13_21_and_34(); +void drawSpiralAnalogClock34_21_and_13(); +void antialiasPixelAR(uint8_t angle, uint8_t dAngle, uint8_t startRadius, uint8_t endRadius, CRGB color, CRGB leds[] = leds, int _NUM_PIXELS = NUM_PIXELS); +#endif +// noise.h -- always defined +void rainbowNoise(); +void rainbowStripeNoise(); +void partyNoise(); +void forestNoise(); +void cloudNoise(); +void fireNoise(); +void fireNoise2(); +void lavaNoise(); +void oceanNoise(); +void blackAndWhiteNoise(); +void blackAndBlueNoise(); -// Local C++ sources that are masquerading as header files -#include "GradientPalettes.h" -#include "Info.h" -#include "Field.h" -#include "FSBrowser.h" -#include "Ping.h" +// noise.h -- only when product defines HAS_POLAR_COORDS to be true +#if HAS_POLAR_COORDS +void palettePolarNoise(); +void gradientPalettePolarNoise(); +void rainbowPolarNoise(); +void rainbowStripePolarNoise(); +void partyPolarNoise(); +void forestPolarNoise(); +void cloudPolarNoise(); +void firePolarNoise(); +void firePolarNoise2(); +void lavaPolarNoise(); +void oceanPolarNoise(); +void blackAndWhitePolarNoise(); +void blackAndBluePolarNoise(); +#endif +// pacifica.h / prideplayground.h / colorwavesplayground.h +void pacifica_loop(); +void pridePlayground(); +void colorWavesPlayground(); +#if IS_FIBONACCI +void pacifica_fibonacci_loop(); +void pridePlaygroundFibonacci(); +void colorWavesPlaygroundFibonacci(); +#endif diff --git a/esp8266-fastled-webserver/config.h b/esp8266-fastled-webserver/config.h index 7def55e1..9c081df9 100644 --- a/esp8266-fastled-webserver/config.h +++ b/esp8266-fastled-webserver/config.h @@ -24,7 +24,7 @@ // When compiling from Arduino, you can edit this file. // When compiling from PlatformIO, this is a reference for compiler flags. -#define PRODUCT_DEFAULT +// #define PRODUCT_DEFAULT // #define PRODUCT_FIBONACCI512 // #define PRODUCT_FIBONACCI256 // #define PRODUCT_FIBONACCI128 @@ -35,7 +35,7 @@ // #define PRODUCT_FIBONACCI32 // #define PRODUCT_KRAKEN64 // #define PRODUCT_ESP8266_THING // aka parallel (6-output) -// #define PRODUCT_1628_RINGS +#define PRODUCT_1628_RINGS // //////////////////////////////////////////////////////////////////////////////////////////////////// // Additional configuration options ... defaults shown @@ -48,7 +48,7 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////// // Include the configuration files for this build // //////////////////////////////////////////////////////////////////////////////////////////////////// -#if 1 +#if 1 // just for collapsing // Product-specific configuration #if defined(PRODUCT_DEFAULT) #include "include\configs\product\default.h" @@ -86,7 +86,7 @@ // //////////////////////////////////////////////////////////////////////////////////////////////////// // Set defaults for optional values // //////////////////////////////////////////////////////////////////////////////////////////////////// -#if 1 +#if 1 // just for collapsing #if !defined(UTC_OFFSET_IN_SECONDS) #define UTC_OFFSET_IN_SECONDS (-6L * 60L * 60L) // UTC-6 (East-coast US ... no DST support) #endif @@ -99,7 +99,7 @@ // Validate configuration options // //////////////////////////////////////////////////////////////////////////////////////////////////// -#if 1 +#if 1 // just for collapsing #if !defined(LED_TYPE) #error "LED_TYPE must be defined by product" #endif diff --git a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino index e9b021a8..2af84642 100644 --- a/esp8266-fastled-webserver/esp8266-fastled-webserver.ino +++ b/esp8266-fastled-webserver/esp8266-fastled-webserver.ino @@ -18,14 +18,6 @@ #include "common.h" - - -#if defined(ENABLE_IR) - IRrecv irReceiver(RECV_PIN); -#endif - - - WiFiManager wifiManager; ESP8266WebServer webServer(80); //WebSocketsServer webSocketsServer = WebSocketsServer(81); @@ -37,13 +29,10 @@ NTPClient timeClient(ntpUDP, "pool.ntp.org", UTC_OFFSET_IN_SECONDS, NTP_UPDATE_T String nameString; - - - CRGB leds[NUM_PIXELS]; const uint8_t brightnessCount = 5; -uint8_t brightnessMap[brightnessCount] = { 16, 32, 64, 128, 255 }; +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 @@ -90,26 +79,31 @@ CRGB solidColor = CRGB::Blue; // scale the brightness of all pixels down void dimAll(byte value) { - // TODO: use auto and C++11 style indexing - for (int i = 0; i < NUM_PIXELS; i++) { - leds[i].nscale8(value); + for (auto led : leds) { + led.nscale8(value); } } - -// These are actually C++ source files, not header files.... -#include "Twinkles.h" -#include "TwinkleFOX.h" - -#include "Map.h" -#include "Noise.h" -#include "Pacifica.h" -#include "PridePlayground.h" -#include "ColorWavesPlayground.h" - // List of patterns to cycle through. Each is defined as a separate function below. -PatternAndNameList patterns = { +// 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" }, @@ -117,23 +111,24 @@ PatternAndNameList patterns = { { colorWaves, "Color Waves" }, -#if HAS_POLAR_COORDS // really a wrong name... and likely doing way more computation than necessary +#if HAS_COORDINATE_MAP // really a wrong name... and likely doing way more computation than necessary { radarSweepPalette, "Radar Sweep Palette" }, - // noise patterns (XY and 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" }, - { rainbowStripeNoise, "Rainbow Stripe 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 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 @@ -161,7 +156,7 @@ PatternAndNameList patterns = { { pacifica_fibonacci_loop, "Pacifica Fibonacci" }, #endif -#if IS_FIBONACCI || HAS_COORDINATE_MAP +#if HAS_COORDINATE_MAP // matrix patterns { anglePalette, "Angle Palette" }, { radiusPalette, "Radius Palette" }, @@ -248,7 +243,7 @@ PatternAndNameList patterns = { { strandTest, "Strand Test" }, - { showSolidColor, "Solid Color" } + { showSolidColor, "Solid Color" } // This *must* be the last pattern }; const uint8_t patternCount = ARRAY_SIZE2(patterns); @@ -277,68 +272,12 @@ 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 -// Ugly macro-like constexpr, used for FastLED template arguments -template -constexpr int LedOffset() { - static_assert(ONE_BASED_OUTPUT_CHANNEL <= PARALLEL_OUTPUT_CHANNELS, ""); - static_assert(ONE_BASED_OUTPUT_CHANNEL >= 1, ""); - return 0 // this would be much simpler with C++14 - #if PARALLEL_OUTPUT_CHANNELS >= 2 - + ((ONE_BASED_OUTPUT_CHANNEL >= 2) ? PIXELS_ON_DATA_PIN_1 : 0) - #endif - #if PARALLEL_OUTPUT_CHANNELS >= 3 - + ((ONE_BASED_OUTPUT_CHANNEL >= 3) ? PIXELS_ON_DATA_PIN_2 : 0) - #endif - #if PARALLEL_OUTPUT_CHANNELS >= 4 - + ((ONE_BASED_OUTPUT_CHANNEL >= 4) ? PIXELS_ON_DATA_PIN_3 : 0) - #endif - #if PARALLEL_OUTPUT_CHANNELS >= 5 - + ((ONE_BASED_OUTPUT_CHANNEL >= 5) ? PIXELS_ON_DATA_PIN_4 : 0) - #endif - #if PARALLEL_OUTPUT_CHANNELS >= 6 - + ((ONE_BASED_OUTPUT_CHANNEL >= 6) ? PIXELS_ON_DATA_PIN_5 : 0) - #endif - ; -} -template -constexpr int LedCount() { - static_assert(ONE_BASED_OUTPUT_CHANNEL <= PARALLEL_OUTPUT_CHANNELS, ""); - static_assert(ONE_BASED_OUTPUT_CHANNEL >= 1, ""); - #if PARALLEL_OUTPUT_CHANNELS == 1 - return NUM_PIXELS; - #else - return // this would be much simpler with C++14 - #if PARALLEL_OUTPUT_CHANNELS >= 6 - (ONE_BASED_OUTPUT_CHANNEL == 6) ? PIXELS_ON_DATA_PIN_6 : - #endif - #if PARALLEL_OUTPUT_CHANNELS >= 5 - (ONE_BASED_OUTPUT_CHANNEL == 5) ? PIXELS_ON_DATA_PIN_5 : - #endif - #if PARALLEL_OUTPUT_CHANNELS >= 4 - (ONE_BASED_OUTPUT_CHANNEL == 4) ? PIXELS_ON_DATA_PIN_4 : - #endif - #if PARALLEL_OUTPUT_CHANNELS >= 3 - (ONE_BASED_OUTPUT_CHANNEL == 3) ? PIXELS_ON_DATA_PIN_3 : - #endif - #if PARALLEL_OUTPUT_CHANNELS >= 2 - (ONE_BASED_OUTPUT_CHANNEL == 2) ? PIXELS_ON_DATA_PIN_2 : - #endif - #if PARALLEL_OUTPUT_CHANNELS >= 1 - (ONE_BASED_OUTPUT_CHANNEL == 1) ? PIXELS_ON_DATA_PIN_1 : - #endif - 0; - #endif -} - - void setup() { WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP WiFi.setSleepMode(WIFI_NONE_SLEEP); @@ -378,7 +317,7 @@ void setup() { 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); @@ -485,7 +424,7 @@ 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); }); @@ -504,7 +443,7 @@ void setup() { 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); }); @@ -512,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); }); @@ -730,9 +669,14 @@ void broadcastString(String name, String value) } // 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(); @@ -765,8 +709,7 @@ void loop() { } checkPingTimer(); - - // handleIrInput(); + handleIrInput(); // empty function when ENABLE_IR is not defined if (power == 0) { fill_solid(leds, NUM_PIXELS, CRGB::Black); @@ -843,305 +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! -// TODO: Combine settings for all builds into a single structure. - -// TODO: Update magic number from 0x55 to 0xAA (or 0x96 or 0x69) - -void readSettings1628Rings() -{ - // 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) { - return; - } - - brightness = EEPROM.read(0); - - currentPatternIndex = EEPROM.read(1); - if (currentPatternIndex >= patternCount) { - currentPatternIndex = patternCount - 1; - } - - byte r = EEPROM.read(2); - byte g = EEPROM.read(3); - byte b = EEPROM.read(4); - - if (r == 0 && g == 0 && b == 0) - { - } - else - { - solidColor = CRGB(r, g, b); - } - - power = EEPROM.read(5); - - autoplay = EEPROM.read(6); - autoplayDuration = EEPROM.read(7); - - currentPaletteIndex = EEPROM.read(8); - if (currentPaletteIndex >= paletteCount) { - currentPaletteIndex = paletteCount - 1; - } - showClock = EEPROM.read(9); - clockBackgroundFade = EEPROM.read(10); - -} -void readSettingsEsp8266Thing() // aka parallel -{ - // 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) { - return; - } - - brightness = EEPROM.read(0); - - currentPatternIndex = EEPROM.read(1); - if (currentPatternIndex >= patternCount) { - currentPatternIndex = patternCount - 1; - } - - byte r = EEPROM.read(2); - byte g = EEPROM.read(3); - byte b = EEPROM.read(4); - - if (r == 0 && g == 0 && b == 0) - { - } - else - { - solidColor = CRGB(r, g, b); - } - - power = EEPROM.read(5); - - autoplay = EEPROM.read(6); - autoplayDuration = EEPROM.read(7); - - currentPaletteIndex = EEPROM.read(8); - if (currentPaletteIndex >= paletteCount) { - currentPaletteIndex = paletteCount - 1; - } -} -void readSettingsKraken64() +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; } @@ -1179,505 +832,39 @@ void readSettingsKraken64() cooling = EEPROM.read(11); sparking = EEPROM.read(12); -} -void readSettingsFib32() -{ - // 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) { - return; - } - - brightness = EEPROM.read(0); - - currentPatternIndex = EEPROM.read(1); - if (currentPatternIndex >= patternCount) { - currentPatternIndex = patternCount - 1; - } - byte r = EEPROM.read(2); - byte g = EEPROM.read(3); - byte b = EEPROM.read(4); - - if (r == 0 && g == 0 && b == 0) - { - } - else - { - solidColor = CRGB(r, g, b); - } - - power = EEPROM.read(5); - - autoplay = EEPROM.read(6); - autoplayDuration = EEPROM.read(7); - - currentPaletteIndex = EEPROM.read(8); - if (currentPaletteIndex >= paletteCount) { - currentPaletteIndex = paletteCount - 1; - } + coolLikeIncandescent = EEPROM.read(13); - showClock = EEPROM.read(9); - clockBackgroundFade = EEPROM.read(10); -} -void readSettingsFib64() -{ - // 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) { - return; - } - - brightness = EEPROM.read(0); - - currentPatternIndex = EEPROM.read(1); - if (currentPatternIndex >= patternCount) { - currentPatternIndex = patternCount - 1; - } - - byte r = EEPROM.read(2); - byte g = EEPROM.read(3); - byte b = EEPROM.read(4); - - if (r == 0 && g == 0 && b == 0) - { - } - else - { - solidColor = CRGB(r, g, b); - } - - power = EEPROM.read(5); - - autoplay = EEPROM.read(6); - autoplayDuration = EEPROM.read(7); - - currentPaletteIndex = EEPROM.read(8); - if (currentPaletteIndex >= paletteCount) { - currentPaletteIndex = paletteCount - 1; - } - - showClock = EEPROM.read(9); - clockBackgroundFade = EEPROM.read(10); -} -void readSettingsFib128() -{ - // 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) { - return; - } - - brightness = EEPROM.read(0); - - currentPatternIndex = EEPROM.read(1); - if (currentPatternIndex >= patternCount) { - currentPatternIndex = patternCount - 1; - } - - byte r = EEPROM.read(2); - byte g = EEPROM.read(3); - byte b = EEPROM.read(4); - - if (r == 0 && g == 0 && b == 0) - { - } - else - { - solidColor = CRGB(r, g, b); - } - - power = EEPROM.read(5); - - autoplay = EEPROM.read(6); - autoplayDuration = EEPROM.read(7); - - currentPaletteIndex = EEPROM.read(8); - if (currentPaletteIndex >= paletteCount) { - currentPaletteIndex = paletteCount - 1; - } - - twinkleSpeed = EEPROM.read(9); - twinkleDensity = EEPROM.read(10); - - cooling = EEPROM.read(11); - sparking = EEPROM.read(12); - - coolLikeIncandescent = EEPROM.read(13); - - showClock = EEPROM.read(14); - clockBackgroundFade = EEPROM.read(15); -} -void readSettingsFib256() -{ - // 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) { - return; - } - - brightness = EEPROM.read(0); - - currentPatternIndex = EEPROM.read(1); - if (currentPatternIndex >= patternCount) { - currentPatternIndex = patternCount - 1; - } - - byte r = EEPROM.read(2); - byte g = EEPROM.read(3); - byte b = EEPROM.read(4); - - if (r == 0 && g == 0 && b == 0) - { - } - else - { - solidColor = CRGB(r, g, b); - } - - power = EEPROM.read(5); - - autoplay = EEPROM.read(6); - autoplayDuration = EEPROM.read(7); - - currentPaletteIndex = EEPROM.read(8); - if (currentPaletteIndex >= paletteCount) { - currentPaletteIndex = paletteCount - 1; - } - showClock = EEPROM.read(9); - clockBackgroundFade = EEPROM.read(10); - - // twinkleSpeed = EEPROM.read(9); - // twinkleDensity = EEPROM.read(10); - - // cooling = EEPROM.read(11); - // sparking = EEPROM.read(12); - - // coolLikeIncandescent = EEPROM.read(13); -} -void readSettingsFib512() -{ - // 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) { - return; - } - - brightness = EEPROM.read(0); - - currentPatternIndex = EEPROM.read(1); - if (currentPatternIndex >= patternCount) { - currentPatternIndex = patternCount - 1; - } - - byte r = EEPROM.read(2); - byte g = EEPROM.read(3); - byte b = EEPROM.read(4); - - if (r == 0 && g == 0 && b == 0) - { - } - else - { - solidColor = CRGB(r, g, b); - } - - power = EEPROM.read(5); - - autoplay = EEPROM.read(6); - autoplayDuration = EEPROM.read(7); - - currentPaletteIndex = EEPROM.read(8); - if (currentPaletteIndex >= paletteCount) { - currentPaletteIndex = paletteCount - 1; - } - twinkleSpeed = EEPROM.read(9); - twinkleDensity = EEPROM.read(10); - - cooling = EEPROM.read(11); - sparking = EEPROM.read(12); - - coolLikeIncandescent = EEPROM.read(13); - - showClock = EEPROM.read(14); - clockBackgroundFade = EEPROM.read(15); -} -void readSettingsDefaultProduct() -{ - // 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) { - return; - } - - brightness = EEPROM.read(0); - - currentPatternIndex = EEPROM.read(1); - if (currentPatternIndex >= patternCount) { - currentPatternIndex = patternCount - 1; - } - - byte r = EEPROM.read(2); - byte g = EEPROM.read(3); - byte b = EEPROM.read(4); - - if (r == 0 && g == 0 && b == 0) - { - } - else - { - solidColor = CRGB(r, g, b); - } - - power = EEPROM.read(5); - - autoplay = EEPROM.read(6); - autoplayDuration = EEPROM.read(7); - - currentPaletteIndex = EEPROM.read(8); - if (currentPaletteIndex >= paletteCount) { - currentPaletteIndex = paletteCount - 1; - } - - twinkleSpeed = EEPROM.read(9); - twinkleDensity = EEPROM.read(10); - - cooling = EEPROM.read(11); - sparking = EEPROM.read(12); - - coolLikeIncandescent = EEPROM.read(13); -} - -void readSettings() { - #if defined (PRODUCT_1628_RINGS) - readSettings1628Rings(); - #elif defined(PRODUCT_ESP8266_THING) - readSettingsEsp8266Thing(); - #elif defined(PRODUCT_KRAKEN64) - readSettingsKraken64(); - #elif defined(PRODUCT_FIBONACCI512) - readSettingsFib512(); - #elif defined(PRODUCT_FIBONACCI256) - readSettingsFib256(); - #elif defined(PRODUCT_FIBONACCI128) - readSettingsFib128(); - #elif defined(PRODUCT_FIBONACCI64_FULL) || defined(PRODUCT_FIBONACCI64_MINI) || defined(PRODUCT_FIBONACCI64_MICRO) || defined(PRODUCT_FIBONACCI64_NANO) - readSettingsFib64(); - #elif defined(PRODUCT_FIBONACCI32) - readSettingsFib32(); - #elif defined(PRODUCT_DEFAULT) - readSettingsDefaultProduct(); - #else - #error "readSettings() not defined for product?" - #endif -} -void writeAndCommitSettings1628Rings() { - EEPROM.write(0, brightness); - EEPROM.write(1, currentPatternIndex); - EEPROM.write(2, solidColor.r); - EEPROM.write(3, solidColor.g); - EEPROM.write(4, solidColor.b); - EEPROM.write(5, power); - EEPROM.write(6, autoplay); - EEPROM.write(7, autoplayDuration); - EEPROM.write(8, currentPaletteIndex); - EEPROM.write(9, showClock); - EEPROM.write(10, clockBackgroundFade); - - EEPROM.write(511, 55); - EEPROM.commit(); -} -void writeAndCommitSettingsEsp8266Thing() // aka parallel -{ - EEPROM.write(0, brightness); - EEPROM.write(1, currentPatternIndex); - EEPROM.write(2, solidColor.r); - EEPROM.write(3, solidColor.g); - EEPROM.write(4, solidColor.b); - EEPROM.write(5, power); - EEPROM.write(6, autoplay); - EEPROM.write(7, autoplayDuration); - EEPROM.write(8, currentPaletteIndex); - EEPROM.write(9, twinkleSpeed); - EEPROM.write(10, twinkleDensity); - EEPROM.write(11, cooling); - EEPROM.write(12, sparking); - - EEPROM.write(511, 55); - EEPROM.commit(); -} -void writeAndCommitSettingsKraken64() -{ - EEPROM.write(0, brightness); - EEPROM.write(1, currentPatternIndex); - EEPROM.write(2, solidColor.r); - EEPROM.write(3, solidColor.g); - EEPROM.write(4, solidColor.b); - EEPROM.write(5, power); - EEPROM.write(6, autoplay); - EEPROM.write(7, autoplayDuration); - EEPROM.write(8, currentPaletteIndex); - EEPROM.write(9, twinkleSpeed); - EEPROM.write(10, twinkleDensity); - EEPROM.write(11, cooling); - EEPROM.write(12, sparking); - - EEPROM.write(511, 55); - EEPROM.commit(); -} -void writeAndCommitSettingsFib32() -{ - EEPROM.write(0, brightness); - EEPROM.write(1, currentPatternIndex); - EEPROM.write(2, solidColor.r); - EEPROM.write(3, solidColor.g); - EEPROM.write(4, solidColor.b); - EEPROM.write(5, power); - EEPROM.write(6, autoplay); - EEPROM.write(7, autoplayDuration); - EEPROM.write(8, currentPaletteIndex); - EEPROM.write(9, showClock); // Note: not previously written for Fib64 boards - EEPROM.write(10, clockBackgroundFade); // Note: not previously written for Fib64 boards - EEPROM.write(511, 55); - EEPROM.commit(); -} -void writeAndCommitSettingsFib64() -{ - EEPROM.write(0, brightness); - EEPROM.write(1, currentPatternIndex); - EEPROM.write(2, solidColor.r); - EEPROM.write(3, solidColor.g); - EEPROM.write(4, solidColor.b); - EEPROM.write(5, power); - EEPROM.write(6, autoplay); - EEPROM.write(7, autoplayDuration); - EEPROM.write(8, currentPaletteIndex); - EEPROM.write(9, twinkleSpeed); - EEPROM.write(10, twinkleDensity); - EEPROM.write(11, cooling); - EEPROM.write(12, sparking); - EEPROM.write(13, coolLikeIncandescent); // Note: not previously written for Fib64 boards - EEPROM.write(14, showClock); // Note: not previously written for Fib64 boards - EEPROM.write(15, clockBackgroundFade); // Note: not previously written for Fib64 boards - EEPROM.write(511, 55); - EEPROM.commit(); -} -void writeAndCommitSettingsFib128() -{ - EEPROM.write(0, brightness); - EEPROM.write(1, currentPatternIndex); - EEPROM.write(2, solidColor.r); - EEPROM.write(3, solidColor.g); - EEPROM.write(4, solidColor.b); - EEPROM.write(5, power); - EEPROM.write(6, autoplay); - EEPROM.write(7, autoplayDuration); - EEPROM.write(8, currentPaletteIndex); - EEPROM.write(9, twinkleSpeed); - EEPROM.write(10, twinkleDensity); - EEPROM.write(11, cooling); - EEPROM.write(12, sparking); - EEPROM.write(13, coolLikeIncandescent); - EEPROM.write(14, showClock); - EEPROM.write(15, clockBackgroundFade); - EEPROM.write(511, 55); - EEPROM.commit(); -} -void writeAndCommitSettingsFib256() -{ - EEPROM.write(0, brightness); - EEPROM.write(1, currentPatternIndex); - EEPROM.write(2, solidColor.r); - EEPROM.write(3, solidColor.g); - EEPROM.write(4, solidColor.b); - EEPROM.write(5, power); - EEPROM.write(6, autoplay); - EEPROM.write(7, autoplayDuration); - EEPROM.write(8, currentPaletteIndex); - EEPROM.write(9, showClock); - EEPROM.write(10, clockBackgroundFade); - EEPROM.write(511, 55); - EEPROM.commit(); -} -void writeAndCommitSettingsFib512() -{ - EEPROM.write(0, brightness); - EEPROM.write(1, currentPatternIndex); - EEPROM.write(2, solidColor.r); - EEPROM.write(3, solidColor.g); - EEPROM.write(4, solidColor.b); - EEPROM.write(5, power); - EEPROM.write(6, autoplay); - EEPROM.write(7, autoplayDuration); - EEPROM.write(8, currentPaletteIndex); - EEPROM.write(9, twinkleSpeed); - EEPROM.write(10, twinkleDensity); - EEPROM.write(11, cooling); - EEPROM.write(12, sparking); - EEPROM.write(13, coolLikeIncandescent); - EEPROM.write(14, showClock); - EEPROM.write(15, clockBackgroundFade); - EEPROM.write(511, 55); - EEPROM.commit(); -} -void writeAndCommitSettingsDefaultProduct() -{ - EEPROM.write(0, brightness); - EEPROM.write(1, currentPatternIndex); - EEPROM.write(2, solidColor.r); - EEPROM.write(3, solidColor.g); - EEPROM.write(4, solidColor.b); - EEPROM.write(5, power); - EEPROM.write(6, autoplay); - EEPROM.write(7, autoplayDuration); - EEPROM.write(8, currentPaletteIndex); - EEPROM.write(9, twinkleSpeed); - EEPROM.write(10, twinkleDensity); - EEPROM.write(11, cooling); - EEPROM.write(12, sparking); - - EEPROM.write(511, 55); - EEPROM.commit(); -} - -void writeAndCommitSettings() -{ - #if defined (PRODUCT_1628_RINGS) - writeAndCommitSettings1628Rings(); - #elif defined(PRODUCT_ESP8266_THING) - writeAndCommitSettingsEsp8266Thing(); - #elif defined(PRODUCT_KRAKEN64) - writeAndCommitSettingsKraken64(); - #elif defined(PRODUCT_FIBONACCI512) - writeAndCommitSettingsFib512(); - #elif defined(PRODUCT_FIBONACCI256) - writeAndCommitSettingsFib256(); - #elif defined(PRODUCT_FIBONACCI128) - writeAndCommitSettingsFib128(); - #elif defined(PRODUCT_FIBONACCI64_FULL) || defined(PRODUCT_FIBONACCI64_MINI) || defined(PRODUCT_FIBONACCI64_MICRO) || defined(PRODUCT_FIBONACCI64_NANO) - writeAndCommitSettingsFib64(); - #elif defined(PRODUCT_FIBONACCI32) - writeAndCommitSettingsFib32(); - #elif defined(PRODUCT_DEFAULT) - writeAndCommitSettingsDefaultProduct(); - #else - #error "writeAndCommitSettings() not defined for product?" - #endif + showClock = EEPROM.read(14); + clockBackgroundFade = EEPROM.read(15); +} +void writeAndCommitSettings() { + EEPROM.write(0, brightness); + EEPROM.write(1, currentPatternIndex); + EEPROM.write(2, solidColor.r); + EEPROM.write(3, solidColor.g); + EEPROM.write(4, solidColor.b); + EEPROM.write(5, power); + EEPROM.write(6, autoplay); + EEPROM.write(7, autoplayDuration); + EEPROM.write(8, currentPaletteIndex); + EEPROM.write(9, twinkleSpeed); + EEPROM.write(10, twinkleDensity); + EEPROM.write(11, cooling); + EEPROM.write(12, sparking); + EEPROM.write(13, coolLikeIncandescent); + EEPROM.write(14, showClock); + EEPROM.write(15, clockBackgroundFade); + EEPROM.write(511, SETTINGS_MAGIC_BYTE); + EEPROM.commit(); } 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; @@ -2022,7 +1209,7 @@ void heatMap(const CRGBPalette16& palette, bool up) { 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 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 From 7fbc35bdccf0a6413748a3d0d78cf3801cc6febc Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Sat, 6 Nov 2021 20:05:10 -0700 Subject: [PATCH 13/16] reset default product --- esp8266-fastled-webserver/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/esp8266-fastled-webserver/config.h b/esp8266-fastled-webserver/config.h index 9c081df9..8dd45904 100644 --- a/esp8266-fastled-webserver/config.h +++ b/esp8266-fastled-webserver/config.h @@ -24,7 +24,7 @@ // When compiling from Arduino, you can edit this file. // When compiling from PlatformIO, this is a reference for compiler flags. -// #define PRODUCT_DEFAULT +#define PRODUCT_DEFAULT // #define PRODUCT_FIBONACCI512 // #define PRODUCT_FIBONACCI256 // #define PRODUCT_FIBONACCI128 @@ -35,7 +35,7 @@ // #define PRODUCT_FIBONACCI32 // #define PRODUCT_KRAKEN64 // #define PRODUCT_ESP8266_THING // aka parallel (6-output) -#define PRODUCT_1628_RINGS +// #define PRODUCT_1628_RINGS // //////////////////////////////////////////////////////////////////////////////////////////////////// // Additional configuration options ... defaults shown From 83e5a5128c3232b729edd08a25d4de4d4eb5ca8a Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Sun, 7 Nov 2021 08:41:49 -0800 Subject: [PATCH 14/16] fix typo in static assert text for ESP8266 --- .../include/configs/controller/controller_esp8266.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h b/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h index 69656fdf..9ac16079 100644 --- a/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h +++ b/esp8266-fastled-webserver/include/configs/controller/controller_esp8266.h @@ -20,7 +20,7 @@ #if !defined(ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP8266_H) #define ESP8266_FASTLED_WEBSERVER_CONTROLLER_ESP8266_H -static_assert(PARALLEL_OUTPUT_CHANNELS <= 6, "ESP8266 only supports four parallel outputs"); +static_assert(PARALLEL_OUTPUT_CHANNELS <= 6, "ESP8266 only supports six parallel outputs"); #if !defined(DATA_PIN) #if PARALLEL_OUTPUT_CHANNELS == 1 From c6a03e93f0044994ca43477464710571cb3d6691 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Sun, 7 Nov 2021 08:58:14 -0800 Subject: [PATCH 15/16] Update comments of product template header --- .../configs/product/product_template.h | 49 +++++++++---------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/esp8266-fastled-webserver/include/configs/product/product_template.h b/esp8266-fastled-webserver/include/configs/product/product_template.h index 0d533b72..7ea04679 100644 --- a/esp8266-fastled-webserver/include/configs/product/product_template.h +++ b/esp8266-fastled-webserver/include/configs/product/product_template.h @@ -39,22 +39,31 @@ #define COLOR_ORDER RGB #endif -// NUM_PIXELS is the number of pixels to be +// 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 @@ -134,9 +143,10 @@ // ... // #define PIXELS_ON_DATA_PIN_n zc // -// Up to the number of parallel outputs, -// *AND* the board file must support the required number of channels -// by defining the corresponding pins as follows: +// *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 @@ -144,32 +154,19 @@ // ... // #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 -// Example from Fibonacci512: -// -// #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 - -// By default, no IR support is included. Define ENABLE_IR to enable IR support. + +// // By default, no IR support is included. Define ENABLE_IR to enable IR support. // #define ENABLE_IR -// NOTE: When ENABLE_IR is defined, can also override controller-specific default: -// #define IR_RECV_PIN D99 +// // When ENABLE_IR is defined, can also override controller-specific default: +// // #define IR_RECV_PIN D99 From 7e6e7bbabad43ffadbe9b49e18d4df7e90a31b37 Mon Sep 17 00:00:00 2001 From: Henry Gabryjelski Date: Mon, 8 Nov 2021 16:03:25 -0800 Subject: [PATCH 16/16] fix slash type --- esp8266-fastled-webserver/config.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/esp8266-fastled-webserver/config.h b/esp8266-fastled-webserver/config.h index 8dd45904..d6f98a7e 100644 --- a/esp8266-fastled-webserver/config.h +++ b/esp8266-fastled-webserver/config.h @@ -51,32 +51,32 @@ #if 1 // just for collapsing // Product-specific configuration #if defined(PRODUCT_DEFAULT) - #include "include\configs\product\default.h" + #include "./include/configs/product/default.h" #elif defined(PRODUCT_1628_RINGS) - #include "include\configs\product\1628rings.h" + #include "./include/configs/product/1628rings.h" #elif defined(PRODUCT_KRAKEN64) - #include "include\configs\product\kraken64.h" + #include "./include/configs/product/kraken64.h" #elif defined(PRODUCT_FIBONACCI32) - #include "include\configs\product\fibonacci32.h" + #include "./include/configs/product/fibonacci32.h" #elif defined(PRODUCT_FIBONACCI64_FULL) || defined(PRODUCT_FIBONACCI64_MINI) || defined(PRODUCT_FIBONACCI64_MICRO) || defined(PRODUCT_FIBONACCI64_NANO) - #include "include\configs\product\fibonacci64.h" + #include "./include/configs/product/fibonacci64.h" #elif defined(PRODUCT_FIBONACCI128) - #include "include\configs\product\fibonacci128.h" + #include "./include/configs/product/fibonacci128.h" #elif defined(PRODUCT_FIBONACCI256) - #include "include\configs\product\fibonacci256.h" + #include "./include/configs/product/fibonacci256.h" #elif defined(PRODUCT_FIBONACCI512) - #include "include\configs\product\fibonacci512.h" + #include "./include/configs/product/fibonacci512.h" #elif defined(PRODUCT_ESP8266_THING) // aka parallel - #include "include\configs\product\esp8266_thing.h" + #include "./include/configs/product/esp8266_thing.h" #else #error "Must define product to build against" #endif // Board-specific configuration #if defined(ARDUINO_ARCH_ESP32) - #include "include\configs\controller\controller_esp32.h" + #include "./include/configs/controller/controller_esp32.h" #elif defined(ARDUINO_ARCH_ESP8266) - #include "include\configs\controller\controller_esp8266.h" + #include "./include/configs/controller/controller_esp8266.h" #else #error "Unknown board type ... currently only support ESP8266 and ESP32" #endif