From b784f3ffe3db22cee001642392b183afa5ca72d7 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 14 Aug 2025 14:14:47 -0400 Subject: [PATCH 01/76] Initial Commit - Hooks for MQTT topics and decoders --- library.properties | 4 +- platformio.ini | 7 +-- src/Wippersnapper.cpp | 86 ++++++++++++++++++++++++++++++++++ src/Wippersnapper.h | 5 ++ src/Wippersnapper_demo.ino.cpp | 26 ++++++++++ 5 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/library.properties b/library.properties index 9ef6dc4a2..e0e33a29c 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Adafruit WipperSnapper -version=1.0.0-beta.110 +version=1.0.0-beta.111 author=Adafruit maintainer=Adafruit sentence=Arduino application for Adafruit.io WipperSnapper @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper category=Communication url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino architectures=* -depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306 +depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD diff --git a/platformio.ini b/platformio.ini index 28f065116..25bbc006b 100644 --- a/platformio.ini +++ b/platformio.ini @@ -90,9 +90,9 @@ lib_deps = https://github.com/tyeth/omron-devhub_d6t-arduino.git https://github.com/pstolarz/OneWireNg.git ; COMMENT OUT FOR RP2040/RP2350 BOARDS - https://github.com/milesburton/Arduino-Temperature-Control-Library.git + ;https://github.com/milesburton/Arduino-Temperature-Control-Library.git ; AND UNCOMMENT FOR RP2040/RP2350 BOARDS - ; https://github.com/pstolarz/Arduino-Temperature-Control-Library.git + https://github.com/pstolarz/Arduino-Temperature-Control-Library.git https://github.com/Sensirion/arduino-sht.git https://github.com/Sensirion/arduino-i2c-scd4x.git https://github.com/Sensirion/arduino-i2c-sen5x.git @@ -100,6 +100,7 @@ lib_deps = https://github.com/adafruit/WiFiNINA.git https://github.com/Starmbi/hp_BH1750.git https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git + Adafruit EPD @@ -265,7 +266,7 @@ extends = common:esp32 board = adafruit_magtag29_esp32s2 build_flags = -DARDUINO_MAGTAG29_ESP32S2 -DBOARD_HAS_PSRAM ;set partition to tinyuf2-partitions-4MB.csv as of idf 5.1 -board_build.partitions = tinyuf2-partitions-4MB.csv +board_build.partitions = tinyuf2-partitions-4MB-noota.csv extra_scripts = pre:rename_usb_config.py ; Adafruit Metro ESP32-S2 diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 0a948feaa..185bfeb79 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -1655,6 +1655,37 @@ void cbSignalUARTReq(char *data, uint16_t len) { WS_DEBUG_PRINTLN("ERROR: Unable to decode UART Signal message"); } +/*! + @brief Called when the device receives a new message from the + /display/ topic. + @param data + Incoming data from MQTT broker. + @param len + Length of incoming data. +*/ +void cbDisplayMessage(char *data, uint16_t len) { + WS_DEBUG_PRINTLN("* NEW MESSAGE [Topic: Display]: "); + WS_DEBUG_PRINT(len); + WS_DEBUG_PRINTLN(" bytes."); + // zero-out current buffer + memset(WS._buffer, 0, sizeof(WS._buffer)); + // copy mqtt data into buffer + memcpy(WS._buffer, data, len); + WS.bufSize = len; + + // Set up the payload callback, which will set up the callbacks for + // each oneof payload field once the field tag is known + // TODO: + // WS.msgPixels.cb_payload.funcs.decode = cbDecodePixelsMsg; + + // Decode pixel message from buffer + pb_istream_t istream = pb_istream_from_buffer(WS._buffer, WS.bufSize); + // TODO: Change fields and message type here + if (!ws_pb_decode(&istream, wippersnapper_signal_v1_PixelsRequest_fields, + &WS.msgPixels)) + WS_DEBUG_PRINTLN("ERROR: Unable to decode display message"); +} + /****************************************************************************/ /*! @brief Handles MQTT messages on signal topic until timeout. @@ -2344,6 +2375,61 @@ bool Wippersnapper::generateWSTopics() { WS_DEBUG_PRINTLN("FATAL ERROR: Failed to allocate memory for UART topic!"); return false; } + +// Create d2b display topic +#ifdef USE_PSRAM + WS._topic_signal_display_brkr = (char *)ps_malloc( + sizeof(char) * strlen(WS._config.aio_user) + strlen("/") + + strlen(_device_uid) + strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + + strlen("broker") + strlen(TOPIC_DISPLAY) + 1); +#else + WS._topic_signal_display_brkr = (char *)malloc( + sizeof(char) * strlen(WS._config.aio_user) + strlen("/") + + strlen(_device_uid) + strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + + strlen("broker") + strlen(TOPIC_DISPLAY) + 1); +#endif + if (WS._topic_signal_display_brkr != NULL) { + strcpy(WS._topic_signal_display_brkr, WS._config.aio_user); + strcat(WS._topic_signal_display_brkr, TOPIC_WS); + strcat(WS._topic_signal_display_brkr, _device_uid); + strcat(WS._topic_signal_display_brkr, TOPIC_SIGNALS); + strcat(WS._topic_signal_display_brkr, "broker"); + strcat(WS._topic_signal_display_brkr, TOPIC_DISPLAY); + } else { // malloc failed + WS_DEBUG_PRINTLN("ERROR: Failed to add a display topic!"); + return false; + } + + // Subscribe to the display sub-topic + _topic_signal_display_sub = + new Adafruit_MQTT_Subscribe(WS._mqtt, WS._topic_signal_display_brkr, 1); + WS._mqtt->subscribe(_topic_signal_display_sub); + _topic_signal_display_sub->setCallback(cbDisplayMessage); + +// Create a b2d display topic +#ifdef USE_PSRAM + WS._topic_signal_display_device = (char *)ps_malloc( + sizeof(char) * strlen(WS._config.aio_user) + strlen("/") + + strlen(_device_uid) + strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + + strlen("device") + strlen(TOPIC_DISPLAY) + 1); +#else + WS._topic_signal_display_device = (char *)malloc( + sizeof(char) * strlen(WS._config.aio_user) + strlen("/") + + strlen(_device_uid) + strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + + strlen("device") + strlen(TOPIC_DISPLAY) + 1); +#endif + if (WS._topic_signal_display_device != NULL) { + strcpy(WS._topic_signal_display_device, WS._config.aio_user); + strcat(WS._topic_signal_display_device, TOPIC_WS); + strcat(WS._topic_signal_display_device, _device_uid); + strcat(WS._topic_signal_display_device, TOPIC_SIGNALS); + strcat(WS._topic_signal_display_device, "device"); + strcat(WS._topic_signal_display_device, TOPIC_DISPLAY); + } else { // malloc failed + WS_DEBUG_PRINTLN("ERROR: Failed to add a display topic!"); + return false; + } + return true; } diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index dc3152d01..763335c2e 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -153,6 +153,7 @@ #define TOPIC_INFO "/info/" ///< Registration sub-topic #define TOPIC_SIGNALS "/signals/" ///< Signals sub-topic #define TOPIC_I2C "/i2c" ///< I2C sub-topic +#define TOPIC_DISPLAY "/display" ///< Display sub-topic (EPD, OLED, TFT, etc.) #define MQTT_TOPIC_PIXELS_DEVICE \ "/signals/device/pixel" ///< Pixels device->broker topic #define MQTT_TOPIC_PIXELS_BROKER \ @@ -404,6 +405,8 @@ class Wippersnapper { char *_topic_signal_pixels_device = NULL; /*!< Topic carries pixel messages */ char *_topic_signal_uart_brkr = NULL; /*!< Topic carries UART messages */ char *_topic_signal_uart_device = NULL; /*!< Topic carries UART messages */ + char *_topic_signal_display_brkr = NULL; /*!< Topic carries messages from a device to a broker. */ + char *_topic_signal_display_device = NULL; /*!< Topic carries messages from a broker to a device. */ wippersnapper_signal_v1_CreateSignalRequest _incomingSignalMsg; /*!< Incoming signal message from broker */ @@ -490,6 +493,8 @@ class Wippersnapper { *_topic_signal_pixels_sub; /*!< Subscribes to pixel device topic. */ Adafruit_MQTT_Subscribe *_topic_signal_uart_sub; /*!< Subscribes to signal's UART topic. */ + Adafruit_MQTT_Subscribe + *_topic_signal_display_sub; /*!< Subscription callback for display topic. */ Adafruit_MQTT_Subscribe *_err_sub; /*!< Subscription to Adafruit IO Error topic. */ diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp new file mode 100644 index 000000000..b71ef62ed --- /dev/null +++ b/src/Wippersnapper_demo.ino.cpp @@ -0,0 +1,26 @@ +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpvcrl51_o" +#include +# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +#include "Wippersnapper_Networking.h" +Wippersnapper_WiFi wipper; + + +#define WS_DEBUG +void setup(); +void loop(); +#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +void setup() { + + wipper.provision(); + + Serial.begin(115200); + + + wipper.connect(); + +} + +void loop() { + wipper.run(); +} \ No newline at end of file From 209abea1eb1e5242cdfc4c6b55e771b562e21166 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 14 Aug 2025 16:34:56 -0400 Subject: [PATCH 02/76] Track WipperSnapper_Protobuf add-display-v1 commit --- src/Wippersnapper_demo.ino.cpp | 26 -- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 36 +++ src/wippersnapper/display/v1/display.pb.h | 242 ++++++++++++++++++ src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 8 +- src/wippersnapper/signal/v1/signal.pb.h | 55 +++- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 21 files changed, 355 insertions(+), 44 deletions(-) delete mode 100644 src/Wippersnapper_demo.ino.cpp create mode 100644 src/wippersnapper/display/v1/display.pb.c create mode 100644 src/wippersnapper/display/v1/display.pb.h diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp deleted file mode 100644 index b71ef62ed..000000000 --- a/src/Wippersnapper_demo.ino.cpp +++ /dev/null @@ -1,26 +0,0 @@ -# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpvcrl51_o" -#include -# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -#include "Wippersnapper_Networking.h" -Wippersnapper_WiFi wipper; - - -#define WS_DEBUG -void setup(); -void loop(); -#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -void setup() { - - wipper.provision(); - - Serial.begin(115200); - - - wipper.connect(); - -} - -void loop() { - wipper.run(); -} \ No newline at end of file diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index af570fc40..2cf057a0c 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index 208fbd01c..3e94b59bd 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c new file mode 100644 index 000000000..872d142ef --- /dev/null +++ b/src/wippersnapper/display/v1/display.pb.c @@ -0,0 +1,36 @@ +/* Automatically generated nanopb constant definitions */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ + +#include "wippersnapper/display/v1/display.pb.h" +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +PB_BIND(wippersnapper_display_v1_EpdSpiConfig, wippersnapper_display_v1_EpdSpiConfig, AUTO) + + +PB_BIND(wippersnapper_display_v1_EPDConfig, wippersnapper_display_v1_EPDConfig, AUTO) + + +PB_BIND(wippersnapper_display_v1_EPDWriteOptions, wippersnapper_display_v1_EPDWriteOptions, AUTO) + + +PB_BIND(wippersnapper_display_v1_DisplayAddOrReplace, wippersnapper_display_v1_DisplayAddOrReplace, AUTO) + + +PB_BIND(wippersnapper_display_v1_DisplayRemove, wippersnapper_display_v1_DisplayRemove, AUTO) + + +PB_BIND(wippersnapper_display_v1_DisplayWrite, wippersnapper_display_v1_DisplayWrite, AUTO) + + +PB_BIND(wippersnapper_display_v1_DisplayAddedorReplaced, wippersnapper_display_v1_DisplayAddedorReplaced, AUTO) + + +PB_BIND(wippersnapper_display_v1_DisplayRemoved, wippersnapper_display_v1_DisplayRemoved, AUTO) + + + + + + diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h new file mode 100644 index 000000000..cccad57f0 --- /dev/null +++ b/src/wippersnapper/display/v1/display.pb.h @@ -0,0 +1,242 @@ +/* Automatically generated nanopb header */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ + +#ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED +#define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED +#include +#include "nanopb/nanopb.pb.h" +#include "wippersnapper/i2c/v1/i2c.pb.h" + +#if PB_PROTO_HEADER_VERSION != 40 +#error Regenerate this file with the current version of nanopb generator. +#endif + +/* Enum definitions */ +typedef enum _wippersnapper_display_v1_DisplayType { + wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_UNSPECIFIED = 0, + wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_OLED = 1, + wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_EPD = 2 +} wippersnapper_display_v1_DisplayType; + +typedef enum _wippersnapper_display_v1_EPDMode { + wippersnapper_display_v1_EPDMode_EPD_MODE_UNSPECIFIED = 0, + wippersnapper_display_v1_EPDMode_EPD_MODE_GRAYSCALE4 = 1, + wippersnapper_display_v1_EPDMode_EPD_MODE_MONO = 2 +} wippersnapper_display_v1_EPDMode; + +typedef enum _wippersnapper_display_v1_EPDColors { + wippersnapper_display_v1_EPDColors_EPD_COLORS_UNSPECIFIED = 0, + wippersnapper_display_v1_EPDColors_EPD_COLORS_WHITE = 1, + wippersnapper_display_v1_EPDColors_EPD_COLORS_BLACK = 2, + wippersnapper_display_v1_EPDColors_EPD_COLORS_RED = 3, + wippersnapper_display_v1_EPDColors_EPD_COLORS_GRAY = 4, + wippersnapper_display_v1_EPDColors_EPD_COLORS_DARK = 5, + wippersnapper_display_v1_EPDColors_EPD_COLORS_LIGHT = 6, + wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW = 7 +} wippersnapper_display_v1_EPDColors; + +/* Struct definitions */ +typedef struct _wippersnapper_display_v1_DisplayAddedorReplaced { + bool did_add; +} wippersnapper_display_v1_DisplayAddedorReplaced; + +typedef struct _wippersnapper_display_v1_DisplayRemove { + char name[6]; +} wippersnapper_display_v1_DisplayRemove; + +typedef struct _wippersnapper_display_v1_DisplayRemoved { + bool did_remove; +} wippersnapper_display_v1_DisplayRemoved; + +typedef struct _wippersnapper_display_v1_EPDConfig { + wippersnapper_display_v1_EPDMode mode; + int32_t width; + int32_t height; + char pin_busy[6]; + char pin_reset[6]; +} wippersnapper_display_v1_EPDConfig; + +typedef struct _wippersnapper_display_v1_EPDWriteOptions { + int32_t text_size; + wippersnapper_display_v1_EPDColors color; +} wippersnapper_display_v1_EPDWriteOptions; + +typedef struct _wippersnapper_display_v1_EpdSpiConfig { + int32_t bus; + char pin_dc[6]; + char pin_rst[6]; + char pin_cs[6]; + char pin_sram_cs[6]; + char pin_busy[6]; +} wippersnapper_display_v1_EpdSpiConfig; + +typedef struct _wippersnapper_display_v1_DisplayAddOrReplace { + wippersnapper_display_v1_DisplayType type; + pb_size_t which_interface_type; + union { + wippersnapper_display_v1_EpdSpiConfig spi_epd; + } interface_type; + char name[6]; +} wippersnapper_display_v1_DisplayAddOrReplace; + +typedef struct _wippersnapper_display_v1_DisplayWrite { + char name[6]; + char message[6]; + pb_size_t which_options; + union { + wippersnapper_display_v1_EPDWriteOptions epd_options; + } options; +} wippersnapper_display_v1_DisplayWrite; + + +/* Helper constants for enums */ +#define _wippersnapper_display_v1_DisplayType_MIN wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_UNSPECIFIED +#define _wippersnapper_display_v1_DisplayType_MAX wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_EPD +#define _wippersnapper_display_v1_DisplayType_ARRAYSIZE ((wippersnapper_display_v1_DisplayType)(wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_EPD+1)) + +#define _wippersnapper_display_v1_EPDMode_MIN wippersnapper_display_v1_EPDMode_EPD_MODE_UNSPECIFIED +#define _wippersnapper_display_v1_EPDMode_MAX wippersnapper_display_v1_EPDMode_EPD_MODE_MONO +#define _wippersnapper_display_v1_EPDMode_ARRAYSIZE ((wippersnapper_display_v1_EPDMode)(wippersnapper_display_v1_EPDMode_EPD_MODE_MONO+1)) + +#define _wippersnapper_display_v1_EPDColors_MIN wippersnapper_display_v1_EPDColors_EPD_COLORS_UNSPECIFIED +#define _wippersnapper_display_v1_EPDColors_MAX wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW +#define _wippersnapper_display_v1_EPDColors_ARRAYSIZE ((wippersnapper_display_v1_EPDColors)(wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW+1)) + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Initializer values for message structs */ +#define wippersnapper_display_v1_EpdSpiConfig_init_default {0, "", "", "", "", ""} +#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN, 0, 0, "", ""} +#define wippersnapper_display_v1_EPDWriteOptions_init_default {0, _wippersnapper_display_v1_EPDColors_MIN} +#define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, ""} +#define wippersnapper_display_v1_DisplayRemove_init_default {""} +#define wippersnapper_display_v1_DisplayWrite_init_default {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_default}} +#define wippersnapper_display_v1_DisplayAddedorReplaced_init_default {0} +#define wippersnapper_display_v1_DisplayRemoved_init_default {0} +#define wippersnapper_display_v1_EpdSpiConfig_init_zero {0, "", "", "", "", ""} +#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN, 0, 0, "", ""} +#define wippersnapper_display_v1_EPDWriteOptions_init_zero {0, _wippersnapper_display_v1_EPDColors_MIN} +#define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, ""} +#define wippersnapper_display_v1_DisplayRemove_init_zero {""} +#define wippersnapper_display_v1_DisplayWrite_init_zero {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_zero}} +#define wippersnapper_display_v1_DisplayAddedorReplaced_init_zero {0} +#define wippersnapper_display_v1_DisplayRemoved_init_zero {0} + +/* Field tags (for use in manual encoding/decoding) */ +#define wippersnapper_display_v1_DisplayAddedorReplaced_did_add_tag 1 +#define wippersnapper_display_v1_DisplayRemove_name_tag 1 +#define wippersnapper_display_v1_DisplayRemoved_did_remove_tag 1 +#define wippersnapper_display_v1_EPDConfig_mode_tag 1 +#define wippersnapper_display_v1_EPDConfig_width_tag 2 +#define wippersnapper_display_v1_EPDConfig_height_tag 3 +#define wippersnapper_display_v1_EPDConfig_pin_busy_tag 4 +#define wippersnapper_display_v1_EPDConfig_pin_reset_tag 5 +#define wippersnapper_display_v1_EPDWriteOptions_text_size_tag 1 +#define wippersnapper_display_v1_EPDWriteOptions_color_tag 2 +#define wippersnapper_display_v1_EpdSpiConfig_bus_tag 1 +#define wippersnapper_display_v1_EpdSpiConfig_pin_dc_tag 2 +#define wippersnapper_display_v1_EpdSpiConfig_pin_rst_tag 3 +#define wippersnapper_display_v1_EpdSpiConfig_pin_cs_tag 4 +#define wippersnapper_display_v1_EpdSpiConfig_pin_sram_cs_tag 5 +#define wippersnapper_display_v1_EpdSpiConfig_pin_busy_tag 6 +#define wippersnapper_display_v1_DisplayAddOrReplace_type_tag 1 +#define wippersnapper_display_v1_DisplayAddOrReplace_spi_epd_tag 2 +#define wippersnapper_display_v1_DisplayAddOrReplace_name_tag 3 +#define wippersnapper_display_v1_DisplayWrite_name_tag 1 +#define wippersnapper_display_v1_DisplayWrite_message_tag 2 +#define wippersnapper_display_v1_DisplayWrite_epd_options_tag 3 + +/* Struct field encoding specification for nanopb */ +#define wippersnapper_display_v1_EpdSpiConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, bus, 1) \ +X(a, STATIC, SINGULAR, STRING, pin_dc, 2) \ +X(a, STATIC, SINGULAR, STRING, pin_rst, 3) \ +X(a, STATIC, SINGULAR, STRING, pin_cs, 4) \ +X(a, STATIC, SINGULAR, STRING, pin_sram_cs, 5) \ +X(a, STATIC, SINGULAR, STRING, pin_busy, 6) +#define wippersnapper_display_v1_EpdSpiConfig_CALLBACK NULL +#define wippersnapper_display_v1_EpdSpiConfig_DEFAULT NULL + +#define wippersnapper_display_v1_EPDConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, mode, 1) \ +X(a, STATIC, SINGULAR, INT32, width, 2) \ +X(a, STATIC, SINGULAR, INT32, height, 3) \ +X(a, STATIC, SINGULAR, STRING, pin_busy, 4) \ +X(a, STATIC, SINGULAR, STRING, pin_reset, 5) +#define wippersnapper_display_v1_EPDConfig_CALLBACK NULL +#define wippersnapper_display_v1_EPDConfig_DEFAULT NULL + +#define wippersnapper_display_v1_EPDWriteOptions_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, text_size, 1) \ +X(a, STATIC, SINGULAR, UENUM, color, 2) +#define wippersnapper_display_v1_EPDWriteOptions_CALLBACK NULL +#define wippersnapper_display_v1_EPDWriteOptions_DEFAULT NULL + +#define wippersnapper_display_v1_DisplayAddOrReplace_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, type, 1) \ +X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_epd,interface_type.spi_epd), 2) \ +X(a, STATIC, SINGULAR, STRING, name, 3) +#define wippersnapper_display_v1_DisplayAddOrReplace_CALLBACK NULL +#define wippersnapper_display_v1_DisplayAddOrReplace_DEFAULT NULL +#define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_spi_epd_MSGTYPE wippersnapper_display_v1_EpdSpiConfig + +#define wippersnapper_display_v1_DisplayRemove_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, name, 1) +#define wippersnapper_display_v1_DisplayRemove_CALLBACK NULL +#define wippersnapper_display_v1_DisplayRemove_DEFAULT NULL + +#define wippersnapper_display_v1_DisplayWrite_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, name, 1) \ +X(a, STATIC, SINGULAR, STRING, message, 2) \ +X(a, STATIC, ONEOF, MESSAGE, (options,epd_options,options.epd_options), 3) +#define wippersnapper_display_v1_DisplayWrite_CALLBACK NULL +#define wippersnapper_display_v1_DisplayWrite_DEFAULT NULL +#define wippersnapper_display_v1_DisplayWrite_options_epd_options_MSGTYPE wippersnapper_display_v1_EPDWriteOptions + +#define wippersnapper_display_v1_DisplayAddedorReplaced_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, BOOL, did_add, 1) +#define wippersnapper_display_v1_DisplayAddedorReplaced_CALLBACK NULL +#define wippersnapper_display_v1_DisplayAddedorReplaced_DEFAULT NULL + +#define wippersnapper_display_v1_DisplayRemoved_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, BOOL, did_remove, 1) +#define wippersnapper_display_v1_DisplayRemoved_CALLBACK NULL +#define wippersnapper_display_v1_DisplayRemoved_DEFAULT NULL + +extern const pb_msgdesc_t wippersnapper_display_v1_EpdSpiConfig_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_EPDConfig_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_EPDWriteOptions_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_DisplayAddOrReplace_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemove_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_DisplayWrite_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_DisplayAddedorReplaced_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; + +/* Defines for backwards compatibility with code written before nanopb-0.4.0 */ +#define wippersnapper_display_v1_EpdSpiConfig_fields &wippersnapper_display_v1_EpdSpiConfig_msg +#define wippersnapper_display_v1_EPDConfig_fields &wippersnapper_display_v1_EPDConfig_msg +#define wippersnapper_display_v1_EPDWriteOptions_fields &wippersnapper_display_v1_EPDWriteOptions_msg +#define wippersnapper_display_v1_DisplayAddOrReplace_fields &wippersnapper_display_v1_DisplayAddOrReplace_msg +#define wippersnapper_display_v1_DisplayRemove_fields &wippersnapper_display_v1_DisplayRemove_msg +#define wippersnapper_display_v1_DisplayWrite_fields &wippersnapper_display_v1_DisplayWrite_msg +#define wippersnapper_display_v1_DisplayAddedorReplaced_fields &wippersnapper_display_v1_DisplayAddedorReplaced_msg +#define wippersnapper_display_v1_DisplayRemoved_fields &wippersnapper_display_v1_DisplayRemoved_msg + +/* Maximum encoded size of messages (where known) */ +#define wippersnapper_display_v1_EpdSpiConfig_size 46 +#define wippersnapper_display_v1_EPDConfig_size 38 +#define wippersnapper_display_v1_EPDWriteOptions_size 13 +#define wippersnapper_display_v1_DisplayAddOrReplace_size 57 +#define wippersnapper_display_v1_DisplayRemove_size 7 +#define wippersnapper_display_v1_DisplayWrite_size 29 +#define wippersnapper_display_v1_DisplayAddedorReplaced_size 2 +#define wippersnapper_display_v1_DisplayRemoved_size 2 + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index 483c432c9..1eba2203a 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index 715616f73..6b5266136 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index e1e4dde04..bc76391b7 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 8b5b0f53b..2e0526c92 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 8ed37f9d0..6cf3925d0 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index 14b1a99fe..7137f1c3a 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index e5bcca7f3..9eeaef7dd 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index b8a7f6813..0ea96b211 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index 36cf1c440..3526dbec3 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index d223d7a1c..07a46bfc7 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index eb9b45e93..b951a904b 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index 61b3b809a..21fd141e9 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index 0f0278ac0..357005718 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -48,4 +48,10 @@ PB_BIND(wippersnapper_signal_v1_PWMRequest, wippersnapper_signal_v1_PWMRequest, PB_BIND(wippersnapper_signal_v1_PWMResponse, wippersnapper_signal_v1_PWMResponse, AUTO) +PB_BIND(wippersnapper_signal_v1_DisplayRequest, wippersnapper_signal_v1_DisplayRequest, AUTO) + + +PB_BIND(wippersnapper_signal_v1_DisplayResponse, wippersnapper_signal_v1_DisplayResponse, AUTO) + + diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index e459607f3..f07792306 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED @@ -12,6 +12,7 @@ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #include "wippersnapper/pixels/v1/pixels.pb.h" #include "wippersnapper/uart/v1/uart.pb.h" +#include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. @@ -28,6 +29,25 @@ typedef struct _wippersnapper_signal_v1_CreateSignalRequest { } payload; } wippersnapper_signal_v1_CreateSignalRequest; +typedef struct _wippersnapper_signal_v1_DisplayRequest { + pb_callback_t cb_payload; + pb_size_t which_payload; + union { + wippersnapper_display_v1_DisplayAddOrReplace display_add; + wippersnapper_display_v1_DisplayRemove display_remove; + wippersnapper_display_v1_DisplayWrite display_write; + } payload; +} wippersnapper_signal_v1_DisplayRequest; + +typedef struct _wippersnapper_signal_v1_DisplayResponse { + pb_callback_t cb_payload; + pb_size_t which_payload; + union { + wippersnapper_display_v1_DisplayAddedorReplaced display_added; + wippersnapper_display_v1_DisplayRemoved display_removed; + } payload; +} wippersnapper_signal_v1_DisplayResponse; + typedef struct _wippersnapper_signal_v1_Ds18x20Request { pb_callback_t cb_payload; pb_size_t which_payload; @@ -173,6 +193,8 @@ extern "C" { #define wippersnapper_signal_v1_SignalResponse_init_default {0, {0}} #define wippersnapper_signal_v1_PWMRequest_init_default {{{NULL}, NULL}, 0, {wippersnapper_pwm_v1_PWMAttachRequest_init_default}} #define wippersnapper_signal_v1_PWMResponse_init_default {{{NULL}, NULL}, 0, {wippersnapper_pwm_v1_PWMAttachResponse_init_default}} +#define wippersnapper_signal_v1_DisplayRequest_init_default {{{NULL}, NULL}, 0, {wippersnapper_display_v1_DisplayAddOrReplace_init_default}} +#define wippersnapper_signal_v1_DisplayResponse_init_default {{{NULL}, NULL}, 0, {wippersnapper_display_v1_DisplayAddedorReplaced_init_default}} #define wippersnapper_signal_v1_UARTRequest_init_zero {{{NULL}, NULL}, 0, {wippersnapper_uart_v1_UARTDeviceAttachRequest_init_zero}} #define wippersnapper_signal_v1_UARTResponse_init_zero {{{NULL}, NULL}, 0, {wippersnapper_uart_v1_UARTDeviceAttachResponse_init_zero}} #define wippersnapper_signal_v1_Ds18x20Request_init_zero {{{NULL}, NULL}, 0, {wippersnapper_ds18x20_v1_Ds18x20InitRequest_init_zero}} @@ -187,11 +209,18 @@ extern "C" { #define wippersnapper_signal_v1_SignalResponse_init_zero {0, {0}} #define wippersnapper_signal_v1_PWMRequest_init_zero {{{NULL}, NULL}, 0, {wippersnapper_pwm_v1_PWMAttachRequest_init_zero}} #define wippersnapper_signal_v1_PWMResponse_init_zero {{{NULL}, NULL}, 0, {wippersnapper_pwm_v1_PWMAttachResponse_init_zero}} +#define wippersnapper_signal_v1_DisplayRequest_init_zero {{{NULL}, NULL}, 0, {wippersnapper_display_v1_DisplayAddOrReplace_init_zero}} +#define wippersnapper_signal_v1_DisplayResponse_init_zero {{{NULL}, NULL}, 0, {wippersnapper_display_v1_DisplayAddedorReplaced_init_zero}} /* Field tags (for use in manual encoding/decoding) */ #define wippersnapper_signal_v1_CreateSignalRequest_pin_configs_tag 6 #define wippersnapper_signal_v1_CreateSignalRequest_pin_events_tag 7 #define wippersnapper_signal_v1_CreateSignalRequest_pin_event_tag 15 +#define wippersnapper_signal_v1_DisplayRequest_display_add_tag 1 +#define wippersnapper_signal_v1_DisplayRequest_display_remove_tag 2 +#define wippersnapper_signal_v1_DisplayRequest_display_write_tag 3 +#define wippersnapper_signal_v1_DisplayResponse_display_added_tag 1 +#define wippersnapper_signal_v1_DisplayResponse_display_removed_tag 2 #define wippersnapper_signal_v1_Ds18x20Request_req_ds18x20_init_tag 1 #define wippersnapper_signal_v1_Ds18x20Request_req_ds18x20_deinit_tag 2 #define wippersnapper_signal_v1_Ds18x20Response_resp_ds18x20_init_tag 1 @@ -360,6 +389,24 @@ X(a, STATIC, ONEOF, MSG_W_CB, (payload,attach_response,payload.attach_respo #define wippersnapper_signal_v1_PWMResponse_DEFAULT NULL #define wippersnapper_signal_v1_PWMResponse_payload_attach_response_MSGTYPE wippersnapper_pwm_v1_PWMAttachResponse +#define wippersnapper_signal_v1_DisplayRequest_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MSG_W_CB, (payload,display_add,payload.display_add), 1) \ +X(a, STATIC, ONEOF, MSG_W_CB, (payload,display_remove,payload.display_remove), 2) \ +X(a, STATIC, ONEOF, MSG_W_CB, (payload,display_write,payload.display_write), 3) +#define wippersnapper_signal_v1_DisplayRequest_CALLBACK NULL +#define wippersnapper_signal_v1_DisplayRequest_DEFAULT NULL +#define wippersnapper_signal_v1_DisplayRequest_payload_display_add_MSGTYPE wippersnapper_display_v1_DisplayAddOrReplace +#define wippersnapper_signal_v1_DisplayRequest_payload_display_remove_MSGTYPE wippersnapper_display_v1_DisplayRemove +#define wippersnapper_signal_v1_DisplayRequest_payload_display_write_MSGTYPE wippersnapper_display_v1_DisplayWrite + +#define wippersnapper_signal_v1_DisplayResponse_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MSG_W_CB, (payload,display_added,payload.display_added), 1) \ +X(a, STATIC, ONEOF, MSG_W_CB, (payload,display_removed,payload.display_removed), 2) +#define wippersnapper_signal_v1_DisplayResponse_CALLBACK NULL +#define wippersnapper_signal_v1_DisplayResponse_DEFAULT NULL +#define wippersnapper_signal_v1_DisplayResponse_payload_display_added_MSGTYPE wippersnapper_display_v1_DisplayAddedorReplaced +#define wippersnapper_signal_v1_DisplayResponse_payload_display_removed_MSGTYPE wippersnapper_display_v1_DisplayRemoved + extern const pb_msgdesc_t wippersnapper_signal_v1_UARTRequest_msg; extern const pb_msgdesc_t wippersnapper_signal_v1_UARTResponse_msg; extern const pb_msgdesc_t wippersnapper_signal_v1_Ds18x20Request_msg; @@ -374,6 +421,8 @@ extern const pb_msgdesc_t wippersnapper_signal_v1_CreateSignalRequest_msg; extern const pb_msgdesc_t wippersnapper_signal_v1_SignalResponse_msg; extern const pb_msgdesc_t wippersnapper_signal_v1_PWMRequest_msg; extern const pb_msgdesc_t wippersnapper_signal_v1_PWMResponse_msg; +extern const pb_msgdesc_t wippersnapper_signal_v1_DisplayRequest_msg; +extern const pb_msgdesc_t wippersnapper_signal_v1_DisplayResponse_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define wippersnapper_signal_v1_UARTRequest_fields &wippersnapper_signal_v1_UARTRequest_msg @@ -390,6 +439,8 @@ extern const pb_msgdesc_t wippersnapper_signal_v1_PWMResponse_msg; #define wippersnapper_signal_v1_SignalResponse_fields &wippersnapper_signal_v1_SignalResponse_msg #define wippersnapper_signal_v1_PWMRequest_fields &wippersnapper_signal_v1_PWMRequest_msg #define wippersnapper_signal_v1_PWMResponse_fields &wippersnapper_signal_v1_PWMResponse_msg +#define wippersnapper_signal_v1_DisplayRequest_fields &wippersnapper_signal_v1_DisplayRequest_msg +#define wippersnapper_signal_v1_DisplayResponse_fields &wippersnapper_signal_v1_DisplayResponse_msg /* Maximum encoded size of messages (where known) */ #define wippersnapper_signal_v1_UARTRequest_size 58 @@ -412,6 +463,8 @@ union wippersnapper_signal_v1_CreateSignalRequest_payload_size_union {char f6[(6 #define wippersnapper_signal_v1_SignalResponse_size 2 #define wippersnapper_signal_v1_PWMRequest_size 82 #define wippersnapper_signal_v1_PWMResponse_size 11 +#define wippersnapper_signal_v1_DisplayRequest_size 59 +#define wippersnapper_signal_v1_DisplayResponse_size 4 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index a605be6ef..f80b3897b 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index af9364c2a..b51fbcb8e 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Jun 6 19:48:16 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From 71cb68d10c2f8e05b34798e5d1e277c8a81cbb7f Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 14 Aug 2025 16:39:21 -0400 Subject: [PATCH 03/76] Add deserializer hooks --- src/Wippersnapper.cpp | 23 ++++++++++++++++++----- src/Wippersnapper.h | 2 ++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 185bfeb79..1e5808dfc 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -1655,6 +1655,21 @@ void cbSignalUARTReq(char *data, uint16_t len) { WS_DEBUG_PRINTLN("ERROR: Unable to decode UART Signal message"); } +/*! + @brief Deserializes a DisplayRequest message and sends it to the display component. + @param stream + Incoming data stream from buffer. + @param field + Protobuf message's tag type. + @param arg + Optional arguments from decoder calling function. + @returns True if decoded successfully, False otherwise. +*/ +bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) { + // TODO: Need to write deserializer logic here + return true; +} + /*! @brief Called when the device receives a new message from the /display/ topic. @@ -1675,14 +1690,12 @@ void cbDisplayMessage(char *data, uint16_t len) { // Set up the payload callback, which will set up the callbacks for // each oneof payload field once the field tag is known - // TODO: - // WS.msgPixels.cb_payload.funcs.decode = cbDecodePixelsMsg; + WS.msgSignalDisplay.cb_payload.funcs.decode = cbDecodeDisplayMsg; // Decode pixel message from buffer pb_istream_t istream = pb_istream_from_buffer(WS._buffer, WS.bufSize); - // TODO: Change fields and message type here - if (!ws_pb_decode(&istream, wippersnapper_signal_v1_PixelsRequest_fields, - &WS.msgPixels)) + if (!ws_pb_decode(&istream, wippersnapper_signal_v1_DisplayRequest_fields, + &WS.msgSignalDisplay)) WS_DEBUG_PRINTLN("ERROR: Unable to decode display message"); } diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 763335c2e..20ededd12 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -433,6 +433,8 @@ class Wippersnapper { wippersnapper_signal_v1_UARTRequest msgSignalUART; ///< UARTReq wrapper message + wippersnapper_signal_v1_DisplayRequest msgSignalDisplay; + char *throttleMessage; /*!< Pointer to throttle message data. */ int throttleTime; /*!< Total amount of time to throttle the device, in milliseconds. */ From 967650e5809fbfbb9f543c7dd1ef0a874945edd3 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 15 Aug 2025 12:05:31 -0400 Subject: [PATCH 04/76] Add display component, start handleAdd --- src/Wippersnapper.cpp | 19 ++++++++- src/Wippersnapper.h | 3 ++ src/components/display/controller.cpp | 37 +++++++++++++++++ src/components/display/controller.h | 41 +++++++++++++++++++ src/components/display/hardware.cpp | 58 +++++++++++++++++++++++++++ src/components/display/hardware.h | 45 +++++++++++++++++++++ src/provisioning/sdcard/ws_sdcard.cpp | 0 src/provisioning/sdcard/ws_sdcard.h | 0 8 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 src/components/display/controller.cpp create mode 100644 src/components/display/controller.h create mode 100644 src/components/display/hardware.cpp create mode 100644 src/components/display/hardware.h create mode 100644 src/provisioning/sdcard/ws_sdcard.cpp create mode 100644 src/provisioning/sdcard/ws_sdcard.h diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 1e5808dfc..783186f0f 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -69,6 +69,9 @@ Wippersnapper::Wippersnapper() { // DallasSemi (OneWire) WS._ds18x20Component = new ws_ds18x20(); + + // Display controller + WS._displayController = new DisplayController(); }; /**************************************************************************/ @@ -1666,7 +1669,21 @@ void cbSignalUARTReq(char *data, uint16_t len) { @returns True if decoded successfully, False otherwise. */ bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) { - // TODO: Need to write deserializer logic here + if (field->tag == wippersnapper_signal_v1_DisplayRequest_display_add_tag) { + + // Decode message into a DisplayAddRequest + wippersnapper_display_v1_DisplayAddOrReplace msgAddReq = wippersnapper_display_v1_DisplayAddOrReplace_init_zero; + if (!ws_pb_decode(stream, + wippersnapper_display_v1_DisplayAddOrReplace_fields, + &msgAddReq)) { + WS_DEBUG_PRINTLN("ERROR: Failure decoding DisplayAddOrReplace message!"); + return false; + } + + // Attempt to add or replace a display component + bool did_add = WS._displayController->Handle_Display_AddOrReplace(&msgAddReq); + // TODO: Add response handling and publishing here + return true; } diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 20ededd12..654fd4c66 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -132,6 +132,7 @@ #include "components/pwm/ws_pwm.h" #include "components/servo/ws_servo.h" #include "components/uart/ws_uart.h" +#include "components/display/controller.h" #if defined(USE_TINYUSB) #include "provisioning/tinyusb/Wippersnapper_FS.h" @@ -246,6 +247,7 @@ class ws_pwm; class ws_ds18x20; class ws_pixels; class ws_uart; +class DisplayController; /**************************************************************************/ /*! @@ -369,6 +371,7 @@ class Wippersnapper { ws_servo *_servoComponent; ///< Instance of servo class ws_ds18x20 *_ds18x20Component; ///< Instance of DS18x20 class ws_uart *_uartComponent; ///< Instance of UART class + DisplayController *_displayController; ///< Instance of display controller class // TODO: does this really need to be global? uint8_t _macAddr[6]; /*!< Unique network iface identifier */ diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp new file mode 100644 index 000000000..4790fa923 --- /dev/null +++ b/src/components/display/controller.cpp @@ -0,0 +1,37 @@ +/*! + * @file src/components/display/controller.cpp + * + * Implementation for the display API controller. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#include "controller.h" + +/*! + @brief Constructs a new DisplayController object +*/ +DisplayController::DisplayController() { + // TODO +} + +/*! + @brief Destructor +*/ +DisplayController::DisplayController() { + // TODO +} + +bool DisplayController::Handle_Display_AddOrReplace(wippersnapper_display_v1_DisplayAddOrReplace *msgAdd) { + DisplayHardware *display = new DisplayHardware(); + // Configure display type + display->setType(msgAdd->type); + + return true; // Placeholder +} diff --git a/src/components/display/controller.h b/src/components/display/controller.h new file mode 100644 index 000000000..cf635476e --- /dev/null +++ b/src/components/display/controller.h @@ -0,0 +1,41 @@ +/*! + * @file src/components/display/controller.h + * + * Controller for the display API + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DISPLAY_CONTROLLER_H +#define WS_DISPLAY_CONTROLLER_H +#include "Wippersnapper.h" +#include "hardware.h" + +class Wippersnapper_V2; ///< Forward declaration +class DisplayHardware; ///< Forward declaration + +/**************************************************************************/ +/*! + @brief Routes messages using the display.proto API to the + appropriate hardware and model classes, controls and tracks + the state of displays. +*/ +/**************************************************************************/ +class DisplayController { +public: + DisplayController(); + ~DisplayController(); + bool Handle_Display_AddOrReplace(wippersnapper_display_v1_DisplayAddOrReplace *msgAdd); + //bool Handle_Display_Write(pb_istream_t *stream); + //bool Handle_Display_Remove(pb_istream_t *stream); +private: + //DisplayHardware *_display_strands[MAX_DISPLAY_STRANDS] = { +}; +extern Wippersnapper Ws; ///< Global WS instance +#endif \ No newline at end of file diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp new file mode 100644 index 000000000..254e52da8 --- /dev/null +++ b/src/components/display/hardware.cpp @@ -0,0 +1,58 @@ +/*! + * @file src/components/display/hardware.cpp + * + * Implementation for the display hardware. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#include "controller.h" + +/*! + @brief Constructs a new DisplayHardware object +*/ +DisplayHardware::DisplayHardware() { + _type = wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_UNSPECIFIED; +} + +/*! + @brief Destructor +*/ +DisplayHardware::DisplayHardware() { + // TODO: Clean up display drivers +} + +/*! + @brief Sets the hardware's display type. + @param type + The display type to set. +*/ +void DisplayHardware::setType(wippersnapper_display_v1_DisplayType type) { + _type = type; +} + +/*! + @brief Initializes the display hardware. + @param reset + Whether to reset the display hardware. + @return True if initialization was successful, false otherwise. +*/ +bool DisplayHardware::begin(bool reset) { + return true; // Placeholder for actual initialization logic +} + +/*! + @brief Sets the text size for the display. + @param sz + The size of the text to set. +*/ +void setTextSize(uint8_t sz) { + // Placeholder for setting text size on the display TODO +} + diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h new file mode 100644 index 000000000..89994ffd2 --- /dev/null +++ b/src/components/display/hardware.h @@ -0,0 +1,45 @@ +/*! + * @file src/components/display/hardware.h + * + * Hardware interface for display components. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DISPLAY_HARDWARE_H +#define WS_DISPLAY_HARDWARE_H +#include "Wippersnapper.h" + +#include "Adafruit_ThinkInk.h" + +/**************************************************************************/ +/*! + @brief Interface for interacting with display hardware (TFT, eInk, + OLED, etc.) + This class provides methods to initialize, write to, and + manage the state of display hardware. +*/ +/**************************************************************************/ +class DisplayHardware { +public: + DisplayHardware(); + ~DisplayHardware(); + // High-level API functions + void setType(wippersnapper_display_v1_DisplayType type); + bool begin(bool reset = true); + // API functions to abstract Adafruit_GFX + void setTextSize(uint8_t sz); + + private: + wippersnapper_display_v1_DisplayType _type; ///< Display type + // TODO: Make these drivers instead? + ThinkInk_290_Grayscale4_EAAMFGN *disp_thinkink_grayscale4_eaamfgn = nullptr; //< 2025 MagTag with SSD1680Z chipset + ThinkInk_290_Grayscale4_T5 *disp_thinkink_grayscale4_t5 = nullptr; ///< Pre-2025 MagTag with IL0373 chipset +}; +#endif // WS_DISPLAY_HARDWARE_H \ No newline at end of file diff --git a/src/provisioning/sdcard/ws_sdcard.cpp b/src/provisioning/sdcard/ws_sdcard.cpp new file mode 100644 index 000000000..e69de29bb diff --git a/src/provisioning/sdcard/ws_sdcard.h b/src/provisioning/sdcard/ws_sdcard.h new file mode 100644 index 000000000..e69de29bb From 14ef634f1f1f0a271dcadf583b3ad1520db3da8d Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 15 Aug 2025 12:08:41 -0400 Subject: [PATCH 05/76] Update for Protobuf 23abc52..c83b680 --- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 3 +- src/wippersnapper/display/v1/display.pb.h | 60 ++++++++++++------- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 4 +- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 20 files changed, 61 insertions(+), 40 deletions(-) diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index 2cf057a0c..00a457b16 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index 3e94b59bd..b26b2c85f 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 872d142ef..636b38272 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -34,3 +34,4 @@ PB_BIND(wippersnapper_display_v1_DisplayRemoved, wippersnapper_display_v1_Displa + diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index cccad57f0..a73042ff8 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -35,6 +35,12 @@ typedef enum _wippersnapper_display_v1_EPDColors { wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW = 7 } wippersnapper_display_v1_EPDColors; +typedef enum _wippersnapper_display_v1_EPDThinkInkPanel { + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED = 0, + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_213_GRAYSCALE4_MFGN = 1, + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_213_GRAYSCALE4_T5 = 2 +} wippersnapper_display_v1_EPDThinkInkPanel; + /* Struct definitions */ typedef struct _wippersnapper_display_v1_DisplayAddedorReplaced { bool did_add; @@ -50,6 +56,7 @@ typedef struct _wippersnapper_display_v1_DisplayRemoved { typedef struct _wippersnapper_display_v1_EPDConfig { wippersnapper_display_v1_EPDMode mode; + wippersnapper_display_v1_EPDThinkInkPanel panel; int32_t width; int32_t height; char pin_busy[6]; @@ -72,11 +79,15 @@ typedef struct _wippersnapper_display_v1_EpdSpiConfig { typedef struct _wippersnapper_display_v1_DisplayAddOrReplace { wippersnapper_display_v1_DisplayType type; + char name[64]; pb_size_t which_interface_type; union { wippersnapper_display_v1_EpdSpiConfig spi_epd; } interface_type; - char name[6]; + pb_size_t which_config; + union { + wippersnapper_display_v1_EPDConfig epd_config; + } config; } wippersnapper_display_v1_DisplayAddOrReplace; typedef struct _wippersnapper_display_v1_DisplayWrite { @@ -102,6 +113,10 @@ typedef struct _wippersnapper_display_v1_DisplayWrite { #define _wippersnapper_display_v1_EPDColors_MAX wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW #define _wippersnapper_display_v1_EPDColors_ARRAYSIZE ((wippersnapper_display_v1_EPDColors)(wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW+1)) +#define _wippersnapper_display_v1_EPDThinkInkPanel_MIN wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED +#define _wippersnapper_display_v1_EPDThinkInkPanel_MAX wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_213_GRAYSCALE4_T5 +#define _wippersnapper_display_v1_EPDThinkInkPanel_ARRAYSIZE ((wippersnapper_display_v1_EPDThinkInkPanel)(wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_213_GRAYSCALE4_T5+1)) + #ifdef __cplusplus extern "C" { @@ -109,17 +124,17 @@ extern "C" { /* Initializer values for message structs */ #define wippersnapper_display_v1_EpdSpiConfig_init_default {0, "", "", "", "", ""} -#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN, 0, 0, "", ""} +#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN, _wippersnapper_display_v1_EPDThinkInkPanel_MIN, 0, 0, "", ""} #define wippersnapper_display_v1_EPDWriteOptions_init_default {0, _wippersnapper_display_v1_EPDColors_MIN} -#define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, ""} +#define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} #define wippersnapper_display_v1_DisplayRemove_init_default {""} #define wippersnapper_display_v1_DisplayWrite_init_default {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_default}} #define wippersnapper_display_v1_DisplayAddedorReplaced_init_default {0} #define wippersnapper_display_v1_DisplayRemoved_init_default {0} #define wippersnapper_display_v1_EpdSpiConfig_init_zero {0, "", "", "", "", ""} -#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN, 0, 0, "", ""} +#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN, _wippersnapper_display_v1_EPDThinkInkPanel_MIN, 0, 0, "", ""} #define wippersnapper_display_v1_EPDWriteOptions_init_zero {0, _wippersnapper_display_v1_EPDColors_MIN} -#define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, ""} +#define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} #define wippersnapper_display_v1_DisplayRemove_init_zero {""} #define wippersnapper_display_v1_DisplayWrite_init_zero {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_zero}} #define wippersnapper_display_v1_DisplayAddedorReplaced_init_zero {0} @@ -130,10 +145,11 @@ extern "C" { #define wippersnapper_display_v1_DisplayRemove_name_tag 1 #define wippersnapper_display_v1_DisplayRemoved_did_remove_tag 1 #define wippersnapper_display_v1_EPDConfig_mode_tag 1 -#define wippersnapper_display_v1_EPDConfig_width_tag 2 -#define wippersnapper_display_v1_EPDConfig_height_tag 3 -#define wippersnapper_display_v1_EPDConfig_pin_busy_tag 4 -#define wippersnapper_display_v1_EPDConfig_pin_reset_tag 5 +#define wippersnapper_display_v1_EPDConfig_panel_tag 2 +#define wippersnapper_display_v1_EPDConfig_width_tag 3 +#define wippersnapper_display_v1_EPDConfig_height_tag 4 +#define wippersnapper_display_v1_EPDConfig_pin_busy_tag 5 +#define wippersnapper_display_v1_EPDConfig_pin_reset_tag 6 #define wippersnapper_display_v1_EPDWriteOptions_text_size_tag 1 #define wippersnapper_display_v1_EPDWriteOptions_color_tag 2 #define wippersnapper_display_v1_EpdSpiConfig_bus_tag 1 @@ -143,8 +159,9 @@ extern "C" { #define wippersnapper_display_v1_EpdSpiConfig_pin_sram_cs_tag 5 #define wippersnapper_display_v1_EpdSpiConfig_pin_busy_tag 6 #define wippersnapper_display_v1_DisplayAddOrReplace_type_tag 1 -#define wippersnapper_display_v1_DisplayAddOrReplace_spi_epd_tag 2 -#define wippersnapper_display_v1_DisplayAddOrReplace_name_tag 3 +#define wippersnapper_display_v1_DisplayAddOrReplace_name_tag 2 +#define wippersnapper_display_v1_DisplayAddOrReplace_spi_epd_tag 3 +#define wippersnapper_display_v1_DisplayAddOrReplace_epd_config_tag 4 #define wippersnapper_display_v1_DisplayWrite_name_tag 1 #define wippersnapper_display_v1_DisplayWrite_message_tag 2 #define wippersnapper_display_v1_DisplayWrite_epd_options_tag 3 @@ -162,10 +179,11 @@ X(a, STATIC, SINGULAR, STRING, pin_busy, 6) #define wippersnapper_display_v1_EPDConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, mode, 1) \ -X(a, STATIC, SINGULAR, INT32, width, 2) \ -X(a, STATIC, SINGULAR, INT32, height, 3) \ -X(a, STATIC, SINGULAR, STRING, pin_busy, 4) \ -X(a, STATIC, SINGULAR, STRING, pin_reset, 5) +X(a, STATIC, SINGULAR, UENUM, panel, 2) \ +X(a, STATIC, SINGULAR, INT32, width, 3) \ +X(a, STATIC, SINGULAR, INT32, height, 4) \ +X(a, STATIC, SINGULAR, STRING, pin_busy, 5) \ +X(a, STATIC, SINGULAR, STRING, pin_reset, 6) #define wippersnapper_display_v1_EPDConfig_CALLBACK NULL #define wippersnapper_display_v1_EPDConfig_DEFAULT NULL @@ -177,11 +195,13 @@ X(a, STATIC, SINGULAR, UENUM, color, 2) #define wippersnapper_display_v1_DisplayAddOrReplace_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, type, 1) \ -X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_epd,interface_type.spi_epd), 2) \ -X(a, STATIC, SINGULAR, STRING, name, 3) +X(a, STATIC, SINGULAR, STRING, name, 2) \ +X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_epd,interface_type.spi_epd), 3) \ +X(a, STATIC, ONEOF, MESSAGE, (config,epd_config,config.epd_config), 4) #define wippersnapper_display_v1_DisplayAddOrReplace_CALLBACK NULL #define wippersnapper_display_v1_DisplayAddOrReplace_DEFAULT NULL #define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_spi_epd_MSGTYPE wippersnapper_display_v1_EpdSpiConfig +#define wippersnapper_display_v1_DisplayAddOrReplace_config_epd_config_MSGTYPE wippersnapper_display_v1_EPDConfig #define wippersnapper_display_v1_DisplayRemove_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, name, 1) @@ -227,9 +247,9 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; /* Maximum encoded size of messages (where known) */ #define wippersnapper_display_v1_EpdSpiConfig_size 46 -#define wippersnapper_display_v1_EPDConfig_size 38 +#define wippersnapper_display_v1_EPDConfig_size 40 #define wippersnapper_display_v1_EPDWriteOptions_size 13 -#define wippersnapper_display_v1_DisplayAddOrReplace_size 57 +#define wippersnapper_display_v1_DisplayAddOrReplace_size 157 #define wippersnapper_display_v1_DisplayRemove_size 7 #define wippersnapper_display_v1_DisplayWrite_size 29 #define wippersnapper_display_v1_DisplayAddedorReplaced_size 2 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index 1eba2203a..69d2a9627 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index 6b5266136..fe2b557a2 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index bc76391b7..b8c944c9d 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 2e0526c92..9c0ddf942 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 6cf3925d0..9df314c41 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index 7137f1c3a..25ae1aff9 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index 9eeaef7dd..5da0e72c1 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index 0ea96b211..4a10ef6e2 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index 3526dbec3..eb42b3324 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index 07a46bfc7..daa06cd46 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index b951a904b..42d6b0da8 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index 21fd141e9..7560a3b05 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index 357005718..c7ad0bacf 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index f07792306..9f81099bb 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED @@ -463,7 +463,7 @@ union wippersnapper_signal_v1_CreateSignalRequest_payload_size_union {char f6[(6 #define wippersnapper_signal_v1_SignalResponse_size 2 #define wippersnapper_signal_v1_PWMRequest_size 82 #define wippersnapper_signal_v1_PWMResponse_size 11 -#define wippersnapper_signal_v1_DisplayRequest_size 59 +#define wippersnapper_signal_v1_DisplayRequest_size 160 #define wippersnapper_signal_v1_DisplayResponse_size 4 #ifdef __cplusplus diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index f80b3897b..5caf0a28a 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index b51fbcb8e..a0e91a1a3 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Aug 14 20:22:46 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From c308694233605f51d6a82cf0078bab823e1e245f Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 15 Aug 2025 12:32:32 -0400 Subject: [PATCH 06/76] Routing epd begin thru --- src/components/display/controller.cpp | 5 +- src/components/display/hardware.cpp | 49 +++++++++++++++++++ src/components/display/hardware.h | 6 ++- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 2 +- src/wippersnapper/display/v1/display.pb.h | 18 +++---- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 4 +- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 23 files changed, 83 insertions(+), 35 deletions(-) diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 4790fa923..06b6e72eb 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -32,6 +32,9 @@ bool DisplayController::Handle_Display_AddOrReplace(wippersnapper_display_v1_Dis DisplayHardware *display = new DisplayHardware(); // Configure display type display->setType(msgAdd->type); - + // Configure display based on config type + if (msgAdd->which_config == wippersnapper_display_v1_DisplayAddOrReplace_epd_config_tag) { + display->configureEPD(&msgAdd->config.epd_config, &msgAdd->interface_type.spi_epd); + } return true; // Placeholder } diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 254e52da8..fadeaa63d 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -37,6 +37,55 @@ void DisplayHardware::setType(wippersnapper_display_v1_DisplayType type) { _type = type; } +/*! + @brief Gets the hardware's display type. + @return The current display type. +*/ +wippersnapper_display_v1_DisplayType DisplayHardware::getType() { + return _type; +} + +/*! + @brief Configures the EPD display with the provided configuration. + @param config + Pointer to the EPD configuration structure. + @param spi_config + Pointer to the SPI configuration structure for EPD. + @return True if configuration was successful, False otherwise. +*/ +bool DisplayHardware::beginEPD(wippersnapper_display_v1_EPDConfig *config, wippersnapper_display_v1_EpdSpiConfig *spi_config) { + // Convert pins in config to int16_t instances + int16_t dc = -1, rst = -1, cs = -1, srcs = -1, busy = -1; + dc = (int16_t)atoi(spi_config->pin_dc+ 1); + rst = (int16_t)atoi(spi_config->pin_rst+ 1); + cs = (int16_t)atoi(spi_config->pin_cs+ 1); + srcs = (int16_t)atoi(spi_config->pin_sram_cs+ 1); + busy = (int16_t)atoi(spi_config->pin_busy+ 1); + + // Configure EPD mode + thinkinkmode_t epd_mode; + if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_GRAYSCALE4) { + epd_mode = THINKINK_GRAYSCALE4; + } else if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_MONO) { + epd_mode = THINKINK_MONO; + } else { + epd_mode = THINKINK_MONO; // Default to mono + } + + // Assign driver instance based on panel type + if (config->panel == wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_213_GRAYSCALE4_MFGN) { + _disp_thinkink_grayscale4_eaamfgn = new ThinkInk_290_Grayscale4_EAAMFGN(dc, rst, cs, srcs, busy); + _disp_thinkink_grayscale4_eaamfgn->begin(epd_mode); + } else if (config->panel == wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_213_GRAYSCALE4_T5) { + _disp_thinkink_grayscale4_t5 = new ThinkInk_290_Grayscale4_T5(dc, rst, cs, srcs, busy); + _disp_thinkink_grayscale4_t5->begin(epd_mode); + } else { + return false; // Unsupported panel type + } + + return true; // Configuration successful +} + /*! @brief Initializes the display hardware. @param reset diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 89994ffd2..815f8380b 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -32,6 +32,8 @@ class DisplayHardware { ~DisplayHardware(); // High-level API functions void setType(wippersnapper_display_v1_DisplayType type); + wippersnapper_display_v1_DisplayType getType(); + void beginEPD(wippersnapper_display_v1_EPDConfig *config, wippersnapper_display_v1_EpdSpiConfig *spi_config); bool begin(bool reset = true); // API functions to abstract Adafruit_GFX void setTextSize(uint8_t sz); @@ -39,7 +41,7 @@ class DisplayHardware { private: wippersnapper_display_v1_DisplayType _type; ///< Display type // TODO: Make these drivers instead? - ThinkInk_290_Grayscale4_EAAMFGN *disp_thinkink_grayscale4_eaamfgn = nullptr; //< 2025 MagTag with SSD1680Z chipset - ThinkInk_290_Grayscale4_T5 *disp_thinkink_grayscale4_t5 = nullptr; ///< Pre-2025 MagTag with IL0373 chipset + ThinkInk_290_Grayscale4_EAAMFGN *_disp_thinkink_grayscale4_eaamfgn = nullptr; //< 2025 MagTag with SSD1680Z chipset + ThinkInk_290_Grayscale4_T5 *_disp_thinkink_grayscale4_t5 = nullptr; ///< Pre-2025 MagTag with IL0373 chipset }; #endif // WS_DISPLAY_HARDWARE_H \ No newline at end of file diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index 00a457b16..d325e1ea2 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index b26b2c85f..357aeabe4 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 636b38272..257c9ea07 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index a73042ff8..aeefbbcb5 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -59,8 +59,6 @@ typedef struct _wippersnapper_display_v1_EPDConfig { wippersnapper_display_v1_EPDThinkInkPanel panel; int32_t width; int32_t height; - char pin_busy[6]; - char pin_reset[6]; } wippersnapper_display_v1_EPDConfig; typedef struct _wippersnapper_display_v1_EPDWriteOptions { @@ -124,7 +122,7 @@ extern "C" { /* Initializer values for message structs */ #define wippersnapper_display_v1_EpdSpiConfig_init_default {0, "", "", "", "", ""} -#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN, _wippersnapper_display_v1_EPDThinkInkPanel_MIN, 0, 0, "", ""} +#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN, _wippersnapper_display_v1_EPDThinkInkPanel_MIN, 0, 0} #define wippersnapper_display_v1_EPDWriteOptions_init_default {0, _wippersnapper_display_v1_EPDColors_MIN} #define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} #define wippersnapper_display_v1_DisplayRemove_init_default {""} @@ -132,7 +130,7 @@ extern "C" { #define wippersnapper_display_v1_DisplayAddedorReplaced_init_default {0} #define wippersnapper_display_v1_DisplayRemoved_init_default {0} #define wippersnapper_display_v1_EpdSpiConfig_init_zero {0, "", "", "", "", ""} -#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN, _wippersnapper_display_v1_EPDThinkInkPanel_MIN, 0, 0, "", ""} +#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN, _wippersnapper_display_v1_EPDThinkInkPanel_MIN, 0, 0} #define wippersnapper_display_v1_EPDWriteOptions_init_zero {0, _wippersnapper_display_v1_EPDColors_MIN} #define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} #define wippersnapper_display_v1_DisplayRemove_init_zero {""} @@ -148,8 +146,6 @@ extern "C" { #define wippersnapper_display_v1_EPDConfig_panel_tag 2 #define wippersnapper_display_v1_EPDConfig_width_tag 3 #define wippersnapper_display_v1_EPDConfig_height_tag 4 -#define wippersnapper_display_v1_EPDConfig_pin_busy_tag 5 -#define wippersnapper_display_v1_EPDConfig_pin_reset_tag 6 #define wippersnapper_display_v1_EPDWriteOptions_text_size_tag 1 #define wippersnapper_display_v1_EPDWriteOptions_color_tag 2 #define wippersnapper_display_v1_EpdSpiConfig_bus_tag 1 @@ -181,9 +177,7 @@ X(a, STATIC, SINGULAR, STRING, pin_busy, 6) X(a, STATIC, SINGULAR, UENUM, mode, 1) \ X(a, STATIC, SINGULAR, UENUM, panel, 2) \ X(a, STATIC, SINGULAR, INT32, width, 3) \ -X(a, STATIC, SINGULAR, INT32, height, 4) \ -X(a, STATIC, SINGULAR, STRING, pin_busy, 5) \ -X(a, STATIC, SINGULAR, STRING, pin_reset, 6) +X(a, STATIC, SINGULAR, INT32, height, 4) #define wippersnapper_display_v1_EPDConfig_CALLBACK NULL #define wippersnapper_display_v1_EPDConfig_DEFAULT NULL @@ -247,9 +241,9 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; /* Maximum encoded size of messages (where known) */ #define wippersnapper_display_v1_EpdSpiConfig_size 46 -#define wippersnapper_display_v1_EPDConfig_size 40 +#define wippersnapper_display_v1_EPDConfig_size 26 #define wippersnapper_display_v1_EPDWriteOptions_size 13 -#define wippersnapper_display_v1_DisplayAddOrReplace_size 157 +#define wippersnapper_display_v1_DisplayAddOrReplace_size 143 #define wippersnapper_display_v1_DisplayRemove_size 7 #define wippersnapper_display_v1_DisplayWrite_size 29 #define wippersnapper_display_v1_DisplayAddedorReplaced_size 2 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index 69d2a9627..947c8dddb 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index fe2b557a2..6aa008171 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index b8c944c9d..94777ff2a 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 9c0ddf942..64a591c47 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 9df314c41..60f3b3283 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index 25ae1aff9..5de5a10f4 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index 5da0e72c1..c1e20312a 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index 4a10ef6e2..f2c080b00 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index eb42b3324..ad194786d 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index daa06cd46..8877acde9 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index 42d6b0da8..2ae848799 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index 7560a3b05..0b5851d99 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index c7ad0bacf..bf4939539 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 9f81099bb..2f214bca7 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED @@ -463,7 +463,7 @@ union wippersnapper_signal_v1_CreateSignalRequest_payload_size_union {char f6[(6 #define wippersnapper_signal_v1_SignalResponse_size 2 #define wippersnapper_signal_v1_PWMRequest_size 82 #define wippersnapper_signal_v1_PWMResponse_size 11 -#define wippersnapper_signal_v1_DisplayRequest_size 160 +#define wippersnapper_signal_v1_DisplayRequest_size 146 #define wippersnapper_signal_v1_DisplayResponse_size 4 #ifdef __cplusplus diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index 5caf0a28a..512c97769 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index a0e91a1a3..9cf2ac479 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:07:24 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From fc41a7de828cf124c1aa85ef8e609abbeeedb481 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 15 Aug 2025 13:41:36 -0400 Subject: [PATCH 07/76] Add beginEPD full implementation with safety concerns and a better init flow --- .vscode/settings.json | 13 +- src/components/display/hardware.cpp | 140 +++++++++++++----- src/components/display/hardware.h | 17 ++- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 2 +- src/wippersnapper/display/v1/display.pb.h | 10 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 2 +- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 23 files changed, 151 insertions(+), 67 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 12d7d847e..9356a4952 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,18 @@ { "files.associations": { "limits": "c", - "type_traits": "c" + "type_traits": "c", + "array": "cpp", + "deque": "cpp", + "list": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "string_view": "cpp", + "format": "cpp", + "initializer_list": "cpp", + "span": "cpp" }, "C_Cpp.dimInactiveRegions": true, "dotnet.defaultSolution": "disable", diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index fadeaa63d..c8a4a58c6 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -34,7 +34,7 @@ DisplayHardware::DisplayHardware() { The display type to set. */ void DisplayHardware::setType(wippersnapper_display_v1_DisplayType type) { - _type = type; + _type = type; } /*! @@ -42,7 +42,7 @@ void DisplayHardware::setType(wippersnapper_display_v1_DisplayType type) { @return The current display type. */ wippersnapper_display_v1_DisplayType DisplayHardware::getType() { - return _type; + return _type; } /*! @@ -53,37 +53,106 @@ wippersnapper_display_v1_DisplayType DisplayHardware::getType() { Pointer to the SPI configuration structure for EPD. @return True if configuration was successful, False otherwise. */ -bool DisplayHardware::beginEPD(wippersnapper_display_v1_EPDConfig *config, wippersnapper_display_v1_EpdSpiConfig *spi_config) { - // Convert pins in config to int16_t instances - int16_t dc = -1, rst = -1, cs = -1, srcs = -1, busy = -1; - dc = (int16_t)atoi(spi_config->pin_dc+ 1); - rst = (int16_t)atoi(spi_config->pin_rst+ 1); - cs = (int16_t)atoi(spi_config->pin_cs+ 1); - srcs = (int16_t)atoi(spi_config->pin_sram_cs+ 1); - busy = (int16_t)atoi(spi_config->pin_busy+ 1); - - // Configure EPD mode - thinkinkmode_t epd_mode; - if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_GRAYSCALE4) { - epd_mode = THINKINK_GRAYSCALE4; - } else if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_MONO) { - epd_mode = THINKINK_MONO; - } else { - epd_mode = THINKINK_MONO; // Default to mono - } - - // Assign driver instance based on panel type - if (config->panel == wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_213_GRAYSCALE4_MFGN) { - _disp_thinkink_grayscale4_eaamfgn = new ThinkInk_290_Grayscale4_EAAMFGN(dc, rst, cs, srcs, busy); - _disp_thinkink_grayscale4_eaamfgn->begin(epd_mode); - } else if (config->panel == wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_213_GRAYSCALE4_T5) { - _disp_thinkink_grayscale4_t5 = new ThinkInk_290_Grayscale4_T5(dc, rst, cs, srcs, busy); - _disp_thinkink_grayscale4_t5->begin(epd_mode); - } else { - return false; // Unsupported panel type - } - - return true; // Configuration successful +bool DisplayHardware::beginEPD( + wippersnapper_display_v1_EPDConfig *config, + wippersnapper_display_v1_EpdSpiConfig *spi_config) { + // Validate pointers + if (config == nullptr || spi_config == nullptr) { + return false; + } + + // Validate panel type + if (config->panel == + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED) { + return false; // Unsupported panel type + } + + // Validate mode is a correct EPD mode + if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_UNSPECIFIED) { + return false; // Unsupported mode + } + + // If we already have a display driver assigned to this hardware instance, + // clean it up! + if (_thinkink_driver == + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_MFGN) { + delete _disp_thinkink_grayscale4_eaamfgn; + _disp_thinkink_grayscale4_eaamfgn = nullptr; + _thinkink_driver = + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED; + } else if ( + _thinkink_driver == + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_T5) { + delete _disp_thinkink_grayscale4_t5; + _disp_thinkink_grayscale4_t5 = nullptr; + _thinkink_driver = + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED; + } + + // Parse all SPI bus pins + // Check length + if (strlen(spi_config->pin_dc) < 2 || strlen(spi_config->pin_rst) < 2 || + strlen(spi_config->pin_cs) < 2) { + return false; + } + // SPI pins must start with 'D' + if (spi_config->pin_dc[0] != 'D' || spi_config->pin_rst[0] != 'D' || + spi_config->pin_cs[0] != 'D') { + return false; + } + + // Parse and assign pins + int16_t srcs = -1, busy = -1; + int16_t dc = (int16_t)atoi(spi_config->pin_dc + 1); + int16_t rst = (int16_t)atoi(spi_config->pin_rst + 1); + int16_t cs = (int16_t)atoi(spi_config->pin_cs + 1); + + // Optionally parse SRAM CS and BUSY pins + if (strlen(spi_config->pin_sram_cs) >= 2 && + spi_config->pin_sram_cs[0] == 'D') { + srcs = (int16_t)atoi(spi_config->pin_sram_cs + 1); + } + if (strlen(spi_config->pin_busy) >= 2 && spi_config->pin_busy[0] == 'D') { + busy = (int16_t)atoi(spi_config->pin_busy + 1); + } + + // TODO: Configure SPI bus selection (UNUSED AS OF RIGHT NOW) + + // Configure EPD mode + thinkinkmode_t epd_mode; + if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_GRAYSCALE4) { + epd_mode = THINKINK_GRAYSCALE4; + } else if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_MONO) { + epd_mode = THINKINK_MONO; + } + + // Assign driver instance based on panel type + if (config->panel == + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_MFGN) { + _disp_thinkink_grayscale4_eaamfgn = + new ThinkInk_290_Grayscale4_EAAMFGN(dc, rst, cs, srcs, busy); + if (!_disp_thinkink_grayscale4_eaamfgn) + return false; // Allocation failed + // Initialize the display + _disp_thinkink_grayscale4_eaamfgn->begin(epd_mode); + _thinkink_driver = + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_MFGN; + } else if ( + config->panel == + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_T5) { + _disp_thinkink_grayscale4_t5 = + new ThinkInk_290_Grayscale4_T5(dc, rst, cs, srcs, busy); + if (!_disp_thinkink_grayscale4_t5) + return false; // Allocation failed + // Initialize the display + _disp_thinkink_grayscale4_t5->begin(epd_mode); + _thinkink_driver = + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_T5; + } else { + return false; // Unsupported panel type + } + + return true; // Configuration successful } /*! @@ -93,7 +162,7 @@ bool DisplayHardware::beginEPD(wippersnapper_display_v1_EPDConfig *config, wippe @return True if initialization was successful, false otherwise. */ bool DisplayHardware::begin(bool reset) { - return true; // Placeholder for actual initialization logic + return true; // Placeholder for actual initialization logic } /*! @@ -102,6 +171,5 @@ bool DisplayHardware::begin(bool reset) { The size of the text to set. */ void setTextSize(uint8_t sz) { - // Placeholder for setting text size on the display TODO + // Placeholder for setting text size on the display TODO } - diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 815f8380b..b4fef854e 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -33,15 +33,20 @@ class DisplayHardware { // High-level API functions void setType(wippersnapper_display_v1_DisplayType type); wippersnapper_display_v1_DisplayType getType(); - void beginEPD(wippersnapper_display_v1_EPDConfig *config, wippersnapper_display_v1_EpdSpiConfig *spi_config); + void beginEPD(wippersnapper_display_v1_EPDConfig *config, + wippersnapper_display_v1_EpdSpiConfig *spi_config); bool begin(bool reset = true); // API functions to abstract Adafruit_GFX void setTextSize(uint8_t sz); - private: - wippersnapper_display_v1_DisplayType _type; ///< Display type - // TODO: Make these drivers instead? - ThinkInk_290_Grayscale4_EAAMFGN *_disp_thinkink_grayscale4_eaamfgn = nullptr; //< 2025 MagTag with SSD1680Z chipset - ThinkInk_290_Grayscale4_T5 *_disp_thinkink_grayscale4_t5 = nullptr; ///< Pre-2025 MagTag with IL0373 chipset +private: + wippersnapper_display_v1_DisplayType _type; ///< Display type + wippersnapper_display_v1_EPDThinkInkPanel + _thinkink_driver; ///< ThinkInk driver type + // TODO: Make these drivers instead? + ThinkInk_290_Grayscale4_EAAMFGN *_disp_thinkink_grayscale4_eaamfgn = + nullptr; //< 2025 MagTag with SSD1680Z chipset + ThinkInk_290_Grayscale4_T5 *_disp_thinkink_grayscale4_t5 = + nullptr; ///< Pre-2025 MagTag with IL0373 chipset }; #endif // WS_DISPLAY_HARDWARE_H \ No newline at end of file diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index d325e1ea2..b0f15a4ad 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index 357aeabe4..c74878946 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 257c9ea07..e0ced97b2 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index aeefbbcb5..fb19c2f75 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -37,8 +37,8 @@ typedef enum _wippersnapper_display_v1_EPDColors { typedef enum _wippersnapper_display_v1_EPDThinkInkPanel { wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED = 0, - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_213_GRAYSCALE4_MFGN = 1, - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_213_GRAYSCALE4_T5 = 2 + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_MFGN = 1, + wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_T5 = 2 } wippersnapper_display_v1_EPDThinkInkPanel; /* Struct definitions */ @@ -112,8 +112,8 @@ typedef struct _wippersnapper_display_v1_DisplayWrite { #define _wippersnapper_display_v1_EPDColors_ARRAYSIZE ((wippersnapper_display_v1_EPDColors)(wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW+1)) #define _wippersnapper_display_v1_EPDThinkInkPanel_MIN wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED -#define _wippersnapper_display_v1_EPDThinkInkPanel_MAX wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_213_GRAYSCALE4_T5 -#define _wippersnapper_display_v1_EPDThinkInkPanel_ARRAYSIZE ((wippersnapper_display_v1_EPDThinkInkPanel)(wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_213_GRAYSCALE4_T5+1)) +#define _wippersnapper_display_v1_EPDThinkInkPanel_MAX wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_T5 +#define _wippersnapper_display_v1_EPDThinkInkPanel_ARRAYSIZE ((wippersnapper_display_v1_EPDThinkInkPanel)(wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_T5+1)) #ifdef __cplusplus diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index 947c8dddb..982aa0c74 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index 6aa008171..832684805 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index 94777ff2a..4e0b0d556 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 64a591c47..bb436342e 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 60f3b3283..b36c39da6 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index 5de5a10f4..a43271502 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index c1e20312a..ab8eea0ea 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index f2c080b00..0185e165f 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index ad194786d..4064b8e24 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index 8877acde9..56d380ed1 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index 2ae848799..19195804d 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index 0b5851d99..754f4c0dc 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index bf4939539..2c3c348f9 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 2f214bca7..2426bbac1 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index 512c97769..7c4c78868 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index 9cf2ac479..3a9b70fb2 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 16:18:27 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From 37904f328228703cc304ded481d4fad8b7235304 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 15 Aug 2025 14:17:25 -0400 Subject: [PATCH 08/76] Almost full circle display add --- src/Wippersnapper_demo.ino.cpp | 26 +++++++++++++++++++++++++ src/components/display/controller.cpp | 28 ++++++++++++++++++++++++--- src/components/display/controller.h | 6 +++--- src/components/display/hardware.cpp | 7 ++++--- src/components/display/hardware.h | 6 +++--- 5 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp new file mode 100644 index 000000000..197cd52c5 --- /dev/null +++ b/src/Wippersnapper_demo.ino.cpp @@ -0,0 +1,26 @@ +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpkb6hfvfs" +#include +# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +#include "Wippersnapper_Networking.h" +Wippersnapper_WiFi wipper; + + +#define WS_DEBUG +void setup(); +void loop(); +#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +void setup() { + + wipper.provision(); + + Serial.begin(115200); + + + wipper.connect(); + +} + +void loop() { + wipper.run(); +} \ No newline at end of file diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 06b6e72eb..350b2329f 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -28,13 +28,35 @@ DisplayController::DisplayController() { // TODO } +/*! + @brief Handles a Display_AddOrReplace message. + @param msgAdd + Pointer to a DisplayAddOrReplace message structure. + @return True if the display was added or replaced successfully, false otherwise. +*/ bool DisplayController::Handle_Display_AddOrReplace(wippersnapper_display_v1_DisplayAddOrReplace *msgAdd) { - DisplayHardware *display = new DisplayHardware(); + DisplayHardware *display = new DisplayHardware(msgAdd->name); + // Configure display type display->setType(msgAdd->type); - // Configure display based on config type + + // Attempt to initialize display hardware instance + bool did_begin = false; if (msgAdd->which_config == wippersnapper_display_v1_DisplayAddOrReplace_epd_config_tag) { - display->configureEPD(&msgAdd->config.epd_config, &msgAdd->interface_type.spi_epd); + did_begin = display->beginEPD(&msgAdd->config.epd_config, &msgAdd->interface_type.spi_epd); + } else { + WS_DEBUG_PRINTLN("[display] Unsupported display configuration type!"); + return false; } + + // Check if the display began successfully + if (!did_begin) { + WS_DEBUG_PRINTLN("[display] Failed to initialize display!"); + delete display; // Clean up if initialization failed + return false; + } + + _hw_instances.push_back(display); // Store the display instance + WS_DEBUG_PRINTLN("[display] Display added or replaced successfully!"); return true; // Placeholder } diff --git a/src/components/display/controller.h b/src/components/display/controller.h index cf635476e..3b8c259a8 100644 --- a/src/components/display/controller.h +++ b/src/components/display/controller.h @@ -32,10 +32,10 @@ class DisplayController { DisplayController(); ~DisplayController(); bool Handle_Display_AddOrReplace(wippersnapper_display_v1_DisplayAddOrReplace *msgAdd); - //bool Handle_Display_Write(pb_istream_t *stream); - //bool Handle_Display_Remove(pb_istream_t *stream); + //bool Handle_Display_Remove(...); + //bool Handle_Display_Write(...); private: - //DisplayHardware *_display_strands[MAX_DISPLAY_STRANDS] = { + std::vector _hw_instances; ///< Holds pointers to DisplayHardware instances }; extern Wippersnapper Ws; ///< Global WS instance #endif \ No newline at end of file diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index c8a4a58c6..24a3f3bae 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -17,15 +17,16 @@ /*! @brief Constructs a new DisplayHardware object */ -DisplayHardware::DisplayHardware() { +DisplayHardware::DisplayHardware(const char *name) { + _name = name; ///< Set the name of the hardware instance _type = wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_UNSPECIFIED; } /*! @brief Destructor */ -DisplayHardware::DisplayHardware() { - // TODO: Clean up display drivers +DisplayHardware::~DisplayHardware() { + // TODO } /*! diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index b4fef854e..8e74d7728 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -28,18 +28,18 @@ /**************************************************************************/ class DisplayHardware { public: - DisplayHardware(); + DisplayHardware(const char *name); ~DisplayHardware(); // High-level API functions void setType(wippersnapper_display_v1_DisplayType type); wippersnapper_display_v1_DisplayType getType(); - void beginEPD(wippersnapper_display_v1_EPDConfig *config, - wippersnapper_display_v1_EpdSpiConfig *spi_config); + bool beginEPD(wippersnapper_display_v1_EPDConfig *config, wippersnapper_display_v1_EpdSpiConfig *spi_config); bool begin(bool reset = true); // API functions to abstract Adafruit_GFX void setTextSize(uint8_t sz); private: + const char *_name; ///< Identifies the hardware instance wippersnapper_display_v1_DisplayType _type; ///< Display type wippersnapper_display_v1_EPDThinkInkPanel _thinkink_driver; ///< ThinkInk driver type From ab55789f25d0e5e91bb618ee79ec439d6044f661 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 15 Aug 2025 14:25:20 -0400 Subject: [PATCH 09/76] Implement HandleDisplayRemove --- src/Wippersnapper.cpp | 4 +- src/Wippersnapper_demo.ino.cpp | 26 ---------- src/components/display/controller.cpp | 75 ++++++++++++++++++--------- src/components/display/controller.h | 10 ++-- src/components/display/hardware.cpp | 8 ++- src/components/display/hardware.h | 4 +- 6 files changed, 68 insertions(+), 59 deletions(-) delete mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 783186f0f..1f4aebae0 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -1682,8 +1682,8 @@ bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field, void **ar // Attempt to add or replace a display component bool did_add = WS._displayController->Handle_Display_AddOrReplace(&msgAddReq); - // TODO: Add response handling and publishing here - + // TODO: Add response handling and publishing here, for now it always returns true and doesnt publish back to the broker + } return true; } diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp deleted file mode 100644 index 197cd52c5..000000000 --- a/src/Wippersnapper_demo.ino.cpp +++ /dev/null @@ -1,26 +0,0 @@ -# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpkb6hfvfs" -#include -# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -#include "Wippersnapper_Networking.h" -Wippersnapper_WiFi wipper; - - -#define WS_DEBUG -void setup(); -void loop(); -#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -void setup() { - - wipper.provision(); - - Serial.begin(115200); - - - wipper.connect(); - -} - -void loop() { - wipper.run(); -} \ No newline at end of file diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 350b2329f..1c8e515ea 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -24,7 +24,7 @@ DisplayController::DisplayController() { /*! @brief Destructor */ -DisplayController::DisplayController() { +DisplayController::~DisplayController() { // TODO } @@ -32,31 +32,56 @@ DisplayController::DisplayController() { @brief Handles a Display_AddOrReplace message. @param msgAdd Pointer to a DisplayAddOrReplace message structure. - @return True if the display was added or replaced successfully, false otherwise. + @return True if the display was added or replaced successfully, false + otherwise. */ -bool DisplayController::Handle_Display_AddOrReplace(wippersnapper_display_v1_DisplayAddOrReplace *msgAdd) { - DisplayHardware *display = new DisplayHardware(msgAdd->name); - - // Configure display type - display->setType(msgAdd->type); - - // Attempt to initialize display hardware instance - bool did_begin = false; - if (msgAdd->which_config == wippersnapper_display_v1_DisplayAddOrReplace_epd_config_tag) { - did_begin = display->beginEPD(&msgAdd->config.epd_config, &msgAdd->interface_type.spi_epd); - } else { - WS_DEBUG_PRINTLN("[display] Unsupported display configuration type!"); - return false; - } +bool DisplayController::Handle_Display_AddOrReplace( + wippersnapper_display_v1_DisplayAddOrReplace *msgAdd) { + DisplayHardware *display = new DisplayHardware(msgAdd->name); - // Check if the display began successfully - if (!did_begin) { - WS_DEBUG_PRINTLN("[display] Failed to initialize display!"); - delete display; // Clean up if initialization failed - return false; - } + // Configure display type + display->setType(msgAdd->type); + + // Attempt to initialize display hardware instance + bool did_begin = false; + if (msgAdd->which_config == + wippersnapper_display_v1_DisplayAddOrReplace_epd_config_tag) { + did_begin = display->beginEPD(&msgAdd->config.epd_config, + &msgAdd->interface_type.spi_epd); + } else { + WS_DEBUG_PRINTLN("[display] Unsupported display configuration type!"); + return false; + } + + // Check if the display began successfully + if (!did_begin) { + WS_DEBUG_PRINTLN("[display] Failed to initialize display!"); + delete display; // Clean up if initialization failed + return false; + } - _hw_instances.push_back(display); // Store the display instance - WS_DEBUG_PRINTLN("[display] Display added or replaced successfully!"); - return true; // Placeholder + _hw_instances.push_back(display); // Store the display instance + WS_DEBUG_PRINTLN("[display] Display added or replaced successfully!"); + return true; // Placeholder } + +/*! + @brief Handles a Display_Remove message. + @param msgRemove + Pointer to a DisplayRemove message structure. + @return True if the display was removed successfully, false otherwise. +*/ +bool DisplayController::Handle_Display_Remove( + wippersnapper_display_v1_DisplayRemove *msgRemove) { + // Find the display instance by name + for (auto it = _hw_instances.begin(); it != _hw_instances.end(); ++it) { + if (strcmp((*it)->getName(), msgRemove->name) == 0) { + delete *it; + _hw_instances.erase(it); + WS_DEBUG_PRINTLN("[display] Display removed successfully!"); + return true; + } + } + WS_DEBUG_PRINTLN("[display] Could not remove display, not found!"); + return false; +} \ No newline at end of file diff --git a/src/components/display/controller.h b/src/components/display/controller.h index 3b8c259a8..e203ed9de 100644 --- a/src/components/display/controller.h +++ b/src/components/display/controller.h @@ -31,11 +31,13 @@ class DisplayController { public: DisplayController(); ~DisplayController(); - bool Handle_Display_AddOrReplace(wippersnapper_display_v1_DisplayAddOrReplace *msgAdd); - //bool Handle_Display_Remove(...); - //bool Handle_Display_Write(...); + bool Handle_Display_AddOrReplace( + wippersnapper_display_v1_DisplayAddOrReplace *msgAdd); + bool Handle_Display_Remove(wippersnapper_display_v1_DisplayRemove *msgRemove); + // bool Handle_Display_Write(...); private: - std::vector _hw_instances; ///< Holds pointers to DisplayHardware instances + std::vector + _hw_instances; ///< Holds pointers to DisplayHardware instances }; extern Wippersnapper Ws; ///< Global WS instance #endif \ No newline at end of file diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 24a3f3bae..af21ca07f 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -171,6 +171,12 @@ bool DisplayHardware::begin(bool reset) { @param sz The size of the text to set. */ -void setTextSize(uint8_t sz) { +void DisplayHardware::setTextSize(uint8_t sz) { // Placeholder for setting text size on the display TODO } + +/*! + @brief Gets the name of the display hardware instance. + @return The name of the display hardware instance. +*/ +const char *DisplayHardware::getName() { return _name; } diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 8e74d7728..15c135a7b 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -31,9 +31,11 @@ class DisplayHardware { DisplayHardware(const char *name); ~DisplayHardware(); // High-level API functions + const char *getName(); void setType(wippersnapper_display_v1_DisplayType type); wippersnapper_display_v1_DisplayType getType(); - bool beginEPD(wippersnapper_display_v1_EPDConfig *config, wippersnapper_display_v1_EpdSpiConfig *spi_config); + bool beginEPD(wippersnapper_display_v1_EPDConfig *config, + wippersnapper_display_v1_EpdSpiConfig *spi_config); bool begin(bool reset = true); // API functions to abstract Adafruit_GFX void setTextSize(uint8_t sz); From cf617c5ae9e27a69af63f6a2df25c3d3372fbff0 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 18 Aug 2025 14:04:44 -0400 Subject: [PATCH 10/76] Refactor out hardware file --- src/Wippersnapper.cpp | 99 +++++++++++-------- src/components/display/drivers/dispDrvBase.h | 45 +++++++++ .../dispDrvThinkInkGrayscale4Eaamfgn.h | 51 ++++++++++ src/components/display/hardware.cpp | 48 ++++----- src/components/display/hardware.h | 10 +- .../register/Wippersnapper_Register.cpp | 1 + 6 files changed, 183 insertions(+), 71 deletions(-) create mode 100644 src/components/display/drivers/dispDrvBase.h create mode 100644 src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 1f4aebae0..3ead64bf3 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -1659,7 +1659,8 @@ void cbSignalUARTReq(char *data, uint16_t len) { } /*! - @brief Deserializes a DisplayRequest message and sends it to the display component. + @brief Deserializes a DisplayRequest message and sends it to the display + component. @param stream Incoming data stream from buffer. @param field @@ -1668,11 +1669,13 @@ void cbSignalUARTReq(char *data, uint16_t len) { Optional arguments from decoder calling function. @returns True if decoded successfully, False otherwise. */ -bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) { +bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field, + void **arg) { if (field->tag == wippersnapper_signal_v1_DisplayRequest_display_add_tag) { // Decode message into a DisplayAddRequest - wippersnapper_display_v1_DisplayAddOrReplace msgAddReq = wippersnapper_display_v1_DisplayAddOrReplace_init_zero; + wippersnapper_display_v1_DisplayAddOrReplace msgAddReq = + wippersnapper_display_v1_DisplayAddOrReplace_init_zero; if (!ws_pb_decode(stream, wippersnapper_display_v1_DisplayAddOrReplace_fields, &msgAddReq)) { @@ -1681,8 +1684,10 @@ bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field, void **ar } // Attempt to add or replace a display component - bool did_add = WS._displayController->Handle_Display_AddOrReplace(&msgAddReq); - // TODO: Add response handling and publishing here, for now it always returns true and doesnt publish back to the broker + bool did_add = + WS._displayController->Handle_Display_AddOrReplace(&msgAddReq); + // TODO: Add response handling and publishing here, for now it always + // returns true and doesnt publish back to the broker } return true; } @@ -2406,57 +2411,56 @@ bool Wippersnapper::generateWSTopics() { return false; } -// Create d2b display topic + // /display topic // + + // Pre-determine topic size + topicLen = strlen(WS._config.aio_user) + strlen("/") + strlen(_device_uid) + + strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + strlen("broker") + + strlen(TOPIC_DISPLAY) + 1; + +// Pre-allocate memory for topic #ifdef USE_PSRAM - WS._topic_signal_display_brkr = (char *)ps_malloc( - sizeof(char) * strlen(WS._config.aio_user) + strlen("/") + - strlen(_device_uid) + strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + - strlen("broker") + strlen(TOPIC_DISPLAY) + 1); + WS._topic_signal_display_brkr = (char *)ps_malloc(topicLen); #else - WS._topic_signal_display_brkr = (char *)malloc( - sizeof(char) * strlen(WS._config.aio_user) + strlen("/") + - strlen(_device_uid) + strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + - strlen("broker") + strlen(TOPIC_DISPLAY) + 1); + WS._topic_signal_display_brkr = (char *)malloc(topicLen); #endif + + // Generate the topic if (WS._topic_signal_display_brkr != NULL) { - strcpy(WS._topic_signal_display_brkr, WS._config.aio_user); - strcat(WS._topic_signal_display_brkr, TOPIC_WS); - strcat(WS._topic_signal_display_brkr, _device_uid); - strcat(WS._topic_signal_display_brkr, TOPIC_SIGNALS); - strcat(WS._topic_signal_display_brkr, "broker"); - strcat(WS._topic_signal_display_brkr, TOPIC_DISPLAY); - } else { // malloc failed - WS_DEBUG_PRINTLN("ERROR: Failed to add a display topic!"); + snprintf(WS._topic_signal_display_brkr, topicLen, "%s/wprsnpr/%s%sbroker%s", + WS._config.aio_user, _device_uid, TOPIC_SIGNALS, TOPIC_DISPLAY); + } else { + WS_DEBUG_PRINTLN( + "FATAL ERROR: Failed to allocate memory for DISPLAY topic!"); return false; } - // Subscribe to the display sub-topic + // Subscribe to signal's DISPLAY sub-topic and set callback _topic_signal_display_sub = new Adafruit_MQTT_Subscribe(WS._mqtt, WS._topic_signal_display_brkr, 1); WS._mqtt->subscribe(_topic_signal_display_sub); _topic_signal_display_sub->setCallback(cbDisplayMessage); -// Create a b2d display topic + // Calculate length of the topic for device-to-broker DISPLAY topic + topicLen = strlen(WS._config.aio_user) + strlen("/") + strlen(_device_uid) + + strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + strlen("device") + + strlen(TOPIC_DISPLAY) + 1; + +// Allocate memory for dynamic MQTT topic #ifdef USE_PSRAM - WS._topic_signal_display_device = (char *)ps_malloc( - sizeof(char) * strlen(WS._config.aio_user) + strlen("/") + - strlen(_device_uid) + strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + - strlen("device") + strlen(TOPIC_DISPLAY) + 1); + WS._topic_signal_display_device = (char *)ps_malloc(topicLen); #else - WS._topic_signal_display_device = (char *)malloc( - sizeof(char) * strlen(WS._config.aio_user) + strlen("/") + - strlen(_device_uid) + strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + - strlen("device") + strlen(TOPIC_DISPLAY) + 1); + WS._topic_signal_display_device = (char *)malloc(topicLen); #endif + + // Generate the topic if memory was allocated successfully if (WS._topic_signal_display_device != NULL) { - strcpy(WS._topic_signal_display_device, WS._config.aio_user); - strcat(WS._topic_signal_display_device, TOPIC_WS); - strcat(WS._topic_signal_display_device, _device_uid); - strcat(WS._topic_signal_display_device, TOPIC_SIGNALS); - strcat(WS._topic_signal_display_device, "device"); - strcat(WS._topic_signal_display_device, TOPIC_DISPLAY); - } else { // malloc failed - WS_DEBUG_PRINTLN("ERROR: Failed to add a display topic!"); + snprintf(WS._topic_signal_display_device, topicLen, + "%s/wprsnpr/%s%sdevice%s", WS._config.aio_user, _device_uid, + TOPIC_SIGNALS, TOPIC_DISPLAY); + } else { + WS_DEBUG_PRINTLN( + "FATAL ERROR: Failed to allocate memory for DISPLAY topic!"); return false; } @@ -2953,6 +2957,14 @@ void Wippersnapper::connect() { WS._ui_helper->build_scr_monitor(); #endif + WS.pinCfgCompleted = true; + + // Initialize Digital IO class + WS._digitalGPIO = new Wippersnapper_DigitalGPIO(20); + // Initialize Analog IO class + WS._analogIO = new Wippersnapper_AnalogIO(5, 3.3); + WS._boardStatus = WS_BOARD_DEF_OK; + // Configure hardware while (!WS.pinCfgCompleted) { WS_DEBUG_PRINTLN( @@ -2968,6 +2980,13 @@ void Wippersnapper::connect() { statusLEDFade(GREEN, 3); WS_DEBUG_PRINTLN( "Registration and configuration complete!\nRunning application..."); + + // Print out display topics + WS_DEBUG_PRINTLN("Device-to-Broker DISPLAY topic: "); + WS_DEBUG_PRINTLN(WS._topic_signal_display_device); + WS_DEBUG_PRINTLN("Broker-to-Device DISPLAY topic: "); + WS_DEBUG_PRINTLN(WS._topic_signal_display_brkr); + delay(500); } /**************************************************************************/ diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h new file mode 100644 index 000000000..a95c6d7eb --- /dev/null +++ b/src/components/display/drivers/dispDrvBase.h @@ -0,0 +1,45 @@ +/*! + * @file src/components/display/drivers/dispDrvBase.h + * + * Abstract base class for display drivers. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DISP_DRV_BASE_H +#define WS_DISP_DRV_BASE_H + +#include "Adafruit_ThinkInk.h" +#include "Wippersnapper.h" + +class dispDrvBase { +public: + dispDrvBase(int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs = -1, + int16_t busy = -1) + : _pin_dc(dc), _pin_rst(rst), _pin_cs(cs), _pin_sram_cs(sram_cs), + _pin_busy(busy) { + // Constructor implementation (if we need one) + } + + virtual ~dispDrvBase() { + // Destructor implementation (if we need one) + }; + + // Virtual function to be implemented by derived classes + virtual bool begin(thinkinkmode_t mode, bool reset = true); + +protected: + int16_t _pin_dc; + int16_t _pin_rst; + int16_t _pin_cs; + int16_t _pin_busy; + int16_t _pin_sram_cs; // for optional EPD SRAM chip select +}; + +#endif // WS_DISP_DRV_BASE_H \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h new file mode 100644 index 000000000..0c347d220 --- /dev/null +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -0,0 +1,51 @@ +/*! + * @file src/components/display/drivers/drvDispThinkInkGrayscale4Eaamfgn.h + * + * Driver for ThinkInk 2.9" Grayscale 4-level EAAMFGN display (2025 MagTag). + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DRV_THINKINK_GRAYSCALE4_EAAMFGN_H +#define WS_DRV_THINKINK_GRAYSCALE4_EAAMFGN_H + +#include "dispDrvBase.h" + +class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { +public: + drvDispThinkInkGrayscale4Eaamfgn(int16_t dc, int16_t rst, int16_t cs, + int16_t sram_cs = -1, int16_t busy = -1) + : dispDrvBase(dc, rst, cs, sram_cs, busy), _display(nullptr) {} + + ~drvDispThinkInkGrayscale4Eaamfgn() { + if (_display) { + delete _display; + _display = nullptr; + } + } + + bool begin(thinkinkmode_t mode, bool reset = true) override { + _display = new ThinkInk_290_Grayscale4_EAAMFGN(_pin_dc, _pin_rst, _pin_cs, + _pin_sram_cs, _pin_busy); + if (!_display) + return false; // Allocation failed + + // Initialize the display + _display->begin(mode); + // Clear the display buffer + _display->clearBuffer(); + _display->display(); + return true; + } + +private: + ThinkInk_290_Grayscale4_EAAMFGN *_display; +}; + +#endif // WS_DRV_THINKINK_GRAYSCALE4_EAAMFGN_H \ No newline at end of file diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index af21ca07f..513106a46 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -59,17 +59,20 @@ bool DisplayHardware::beginEPD( wippersnapper_display_v1_EpdSpiConfig *spi_config) { // Validate pointers if (config == nullptr || spi_config == nullptr) { + WS_DEBUG_PRINTLN("[display] EPD config or SPI config is null!"); return false; } // Validate panel type if (config->panel == wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED) { + WS_DEBUG_PRINTLN("[display] Unsupported EPD panel type!"); return false; // Unsupported panel type } // Validate mode is a correct EPD mode if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_UNSPECIFIED) { + WS_DEBUG_PRINTLN("[display] Unsupported EPD mode!"); return false; // Unsupported mode } @@ -81,24 +84,19 @@ bool DisplayHardware::beginEPD( _disp_thinkink_grayscale4_eaamfgn = nullptr; _thinkink_driver = wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED; - } else if ( - _thinkink_driver == - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_T5) { - delete _disp_thinkink_grayscale4_t5; - _disp_thinkink_grayscale4_t5 = nullptr; - _thinkink_driver = - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED; } // Parse all SPI bus pins // Check length if (strlen(spi_config->pin_dc) < 2 || strlen(spi_config->pin_rst) < 2 || strlen(spi_config->pin_cs) < 2) { + WS_DEBUG_PRINTLN("[display] Invalid SPI pin len!"); return false; } // SPI pins must start with 'D' if (spi_config->pin_dc[0] != 'D' || spi_config->pin_rst[0] != 'D' || spi_config->pin_cs[0] != 'D') { + WS_DEBUG_PRINTLN("[display] SPI pins must start with 'D'!"); return false; } @@ -123,33 +121,35 @@ bool DisplayHardware::beginEPD( thinkinkmode_t epd_mode; if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_GRAYSCALE4) { epd_mode = THINKINK_GRAYSCALE4; + WS_DEBUG_PRINTLN("[display] EPD mode: GRAYSCALE4"); } else if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_MONO) { epd_mode = THINKINK_MONO; + WS_DEBUG_PRINTLN("[display] EPD mode: MONO"); } - // Assign driver instance based on panel type + // Configure the EPD driver based on panel type if (config->panel == wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_MFGN) { - _disp_thinkink_grayscale4_eaamfgn = - new ThinkInk_290_Grayscale4_EAAMFGN(dc, rst, cs, srcs, busy); - if (!_disp_thinkink_grayscale4_eaamfgn) - return false; // Allocation failed - // Initialize the display - _disp_thinkink_grayscale4_eaamfgn->begin(epd_mode); + WS_DEBUG_PRINTLN("[display] EPD panel: ThinkInk 290 Grayscale4 MFGN"); _thinkink_driver = wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_MFGN; - } else if ( - config->panel == - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_T5) { - _disp_thinkink_grayscale4_t5 = - new ThinkInk_290_Grayscale4_T5(dc, rst, cs, srcs, busy); - if (!_disp_thinkink_grayscale4_t5) + _disp_thinkink_grayscale4_eaamfgn = + new drvDispThinkInkGrayscale4Eaamfgn(dc, rst, cs, srcs, busy); + if (!_disp_thinkink_grayscale4_eaamfgn) { + WS_DEBUG_PRINTLN("[display] Failed to allocate ThinkInk driver!"); return false; // Allocation failed - // Initialize the display - _disp_thinkink_grayscale4_t5->begin(epd_mode); - _thinkink_driver = - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_T5; + } + if (!_disp_thinkink_grayscale4_eaamfgn->begin(epd_mode)) { + WS_DEBUG_PRINTLN("[display] Failed to initialize ThinkInk driver!"); + delete _disp_thinkink_grayscale4_eaamfgn; // Clean up if initialization + // failed + _disp_thinkink_grayscale4_eaamfgn = nullptr; + return false; // Initialization failed + } + WS_DEBUG_PRINTLN("[display] ThinkInk 290 Grayscale4 MFGN driver " + "initialized successfully!"); } else { + WS_DEBUG_PRINTLN("[display] Unsupported EPD panel type!"); return false; // Unsupported panel type } diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 15c135a7b..6bf8b9513 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -15,8 +15,8 @@ #ifndef WS_DISPLAY_HARDWARE_H #define WS_DISPLAY_HARDWARE_H #include "Wippersnapper.h" - -#include "Adafruit_ThinkInk.h" +#include "drivers/dispDrvBase.h" +#include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h" /**************************************************************************/ /*! @@ -45,10 +45,6 @@ class DisplayHardware { wippersnapper_display_v1_DisplayType _type; ///< Display type wippersnapper_display_v1_EPDThinkInkPanel _thinkink_driver; ///< ThinkInk driver type - // TODO: Make these drivers instead? - ThinkInk_290_Grayscale4_EAAMFGN *_disp_thinkink_grayscale4_eaamfgn = - nullptr; //< 2025 MagTag with SSD1680Z chipset - ThinkInk_290_Grayscale4_T5 *_disp_thinkink_grayscale4_t5 = - nullptr; ///< Pre-2025 MagTag with IL0373 chipset + drvDispThinkInkGrayscale4Eaamfgn *_disp_thinkink_grayscale4_eaamfgn = nullptr; }; #endif // WS_DISPLAY_HARDWARE_H \ No newline at end of file diff --git a/src/components/register/Wippersnapper_Register.cpp b/src/components/register/Wippersnapper_Register.cpp index 522818997..4ad9ec5c4 100644 --- a/src/components/register/Wippersnapper_Register.cpp +++ b/src/components/register/Wippersnapper_Register.cpp @@ -77,6 +77,7 @@ bool Wippersnapper::encodePubRegistrationReq() { /****************************************************************************/ void Wippersnapper::pollRegistrationResp() { // Blocking loop, WDT reset upon failure. + WS._boardStatus = WS_BOARD_DEF_OK; while (WS._boardStatus != WS_BOARD_DEF_OK) { WS_DEBUG_PRINT("Polling for registration message response..."); WS_DEBUG_PRINTLN(WS._boardStatus); From 2743edc6375d91316edfe1d5b6241f88a10483d6 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 18 Aug 2025 14:35:13 -0400 Subject: [PATCH 11/76] last bit of optimization to allow a factory map within hardware.cpp and switch to a default type to allow general api access rather than specific driver access. similar to v2 --- src/Wippersnapper_demo.ino.cpp | 26 ++++++++ src/components/display/hardware.cpp | 94 +++++++++++++++++------------ src/components/display/hardware.h | 6 +- 3 files changed, 87 insertions(+), 39 deletions(-) create mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp new file mode 100644 index 000000000..05fbd12e9 --- /dev/null +++ b/src/Wippersnapper_demo.ino.cpp @@ -0,0 +1,26 @@ +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmp8qooypzx" +#include +# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +#include "Wippersnapper_Networking.h" +Wippersnapper_WiFi wipper; + + +#define WS_DEBUG +void setup(); +void loop(); +#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +void setup() { + + wipper.provision(); + + Serial.begin(115200); + + + wipper.connect(); + +} + +void loop() { + wipper.run(); +} \ No newline at end of file diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 513106a46..2b1cd1297 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -14,6 +14,48 @@ */ #include "controller.h" +/*! + @brief Lambda function to create a dispDrvBase instance +*/ +using FnCreateDispDrv = + std::function; + +// Factory for creating a new display drivers +// NOTE: When you add a new display driver, make sure to add it to the factory! +static const std::map FactoryDrvDisp = { + {"grayscale4_eaamfgn", + [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, + int16_t busy) -> dispDrvBase * { + return new drvDispThinkInkGrayscale4Eaamfgn(dc, rst, cs, sram_cs, busy); + }}}; + +/*! + @brief Creates a new display driver instance based on the driver name. + @param driver_name + The name of the display driver to create. + @param dc + Data/Command pin number. + @param rst + Reset pin number. + @param cs + Chip Select pin number. + @param sram_cs + Optional SRAM Chip Select pin number (default: -1). + @param busy + Optional Busy pin number (default: -1). + @return Pointer to the created display driver instance, or nullptr if the + driver name is not recognized. +*/ +dispDrvBase *CreateDrvDisp(const char *driver_name, int16_t dc, int16_t rst, + int16_t cs, int16_t sram_cs = -1, + int16_t busy = -1) { + auto it = FactoryDrvDisp.find(driver_name); + if (it == FactoryDrvDisp.end()) { + return nullptr; + } + return it->second(dc, rst, cs, sram_cs, busy); +} + /*! @brief Constructs a new DisplayHardware object */ @@ -76,15 +118,8 @@ bool DisplayHardware::beginEPD( return false; // Unsupported mode } - // If we already have a display driver assigned to this hardware instance, - // clean it up! - if (_thinkink_driver == - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_MFGN) { - delete _disp_thinkink_grayscale4_eaamfgn; - _disp_thinkink_grayscale4_eaamfgn = nullptr; - _thinkink_driver = - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED; - } + // TODO: If we already have a display driver assigned to this hardware + // instance, clean it up! // Parse all SPI bus pins // Check length @@ -117,40 +152,25 @@ bool DisplayHardware::beginEPD( // TODO: Configure SPI bus selection (UNUSED AS OF RIGHT NOW) + // Create display driver object using the factory function + _disp_drv_base = CreateDrvDisp(_name, dc, rst, cs, srcs, busy); + if (!_disp_drv_base) { + WS_DEBUG_PRINTLN("[display] Failed to create display driver!"); + return false; // Failed to create display driver + } + // Configure EPD mode - thinkinkmode_t epd_mode; + thinkinkmode_t epd_mode = THINKINK_MONO; if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_GRAYSCALE4) { epd_mode = THINKINK_GRAYSCALE4; WS_DEBUG_PRINTLN("[display] EPD mode: GRAYSCALE4"); - } else if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_MONO) { - epd_mode = THINKINK_MONO; - WS_DEBUG_PRINTLN("[display] EPD mode: MONO"); } - // Configure the EPD driver based on panel type - if (config->panel == - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_MFGN) { - WS_DEBUG_PRINTLN("[display] EPD panel: ThinkInk 290 Grayscale4 MFGN"); - _thinkink_driver = - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_MFGN; - _disp_thinkink_grayscale4_eaamfgn = - new drvDispThinkInkGrayscale4Eaamfgn(dc, rst, cs, srcs, busy); - if (!_disp_thinkink_grayscale4_eaamfgn) { - WS_DEBUG_PRINTLN("[display] Failed to allocate ThinkInk driver!"); - return false; // Allocation failed - } - if (!_disp_thinkink_grayscale4_eaamfgn->begin(epd_mode)) { - WS_DEBUG_PRINTLN("[display] Failed to initialize ThinkInk driver!"); - delete _disp_thinkink_grayscale4_eaamfgn; // Clean up if initialization - // failed - _disp_thinkink_grayscale4_eaamfgn = nullptr; - return false; // Initialization failed - } - WS_DEBUG_PRINTLN("[display] ThinkInk 290 Grayscale4 MFGN driver " - "initialized successfully!"); - } else { - WS_DEBUG_PRINTLN("[display] Unsupported EPD panel type!"); - return false; // Unsupported panel type + if (!_disp_drv_base->begin(epd_mode)) { + WS_DEBUG_PRINTLN("[display] Failed to begin display driver!"); + delete _disp_drv_base; // Clean up if initialization failed + _disp_drv_base = nullptr; + return false; // Failed to begin display driver } return true; // Configuration successful diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 6bf8b9513..0622c5f11 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -17,6 +17,8 @@ #include "Wippersnapper.h" #include "drivers/dispDrvBase.h" #include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h" +#include +#include /**************************************************************************/ /*! @@ -44,7 +46,7 @@ class DisplayHardware { const char *_name; ///< Identifies the hardware instance wippersnapper_display_v1_DisplayType _type; ///< Display type wippersnapper_display_v1_EPDThinkInkPanel - _thinkink_driver; ///< ThinkInk driver type - drvDispThinkInkGrayscale4Eaamfgn *_disp_thinkink_grayscale4_eaamfgn = nullptr; + _thinkink_driver; ///< ThinkInk driver type + dispDrvBase *_disp_drv_base = nullptr; ///< Base display driver }; #endif // WS_DISPLAY_HARDWARE_H \ No newline at end of file From ca75bf0f188b0c994ac794468ed7c70db0d75d43 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 18 Aug 2025 14:46:33 -0400 Subject: [PATCH 12/76] Match 711bf14..000802e --- src/Wippersnapper_demo.ino.cpp | 26 ---------------- src/components/display/hardware.cpp | 18 ----------- src/components/display/hardware.h | 16 ++++++---- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 3 +- src/wippersnapper/display/v1/display.pb.h | 31 ++++++------------- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 4 +-- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 23 files changed, 39 insertions(+), 93 deletions(-) delete mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp deleted file mode 100644 index 05fbd12e9..000000000 --- a/src/Wippersnapper_demo.ino.cpp +++ /dev/null @@ -1,26 +0,0 @@ -# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmp8qooypzx" -#include -# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -#include "Wippersnapper_Networking.h" -Wippersnapper_WiFi wipper; - - -#define WS_DEBUG -void setup(); -void loop(); -#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -void setup() { - - wipper.provision(); - - Serial.begin(115200); - - - wipper.connect(); - -} - -void loop() { - wipper.run(); -} \ No newline at end of file diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 2b1cd1297..30fbc24a4 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -176,24 +176,6 @@ bool DisplayHardware::beginEPD( return true; // Configuration successful } -/*! - @brief Initializes the display hardware. - @param reset - Whether to reset the display hardware. - @return True if initialization was successful, false otherwise. -*/ -bool DisplayHardware::begin(bool reset) { - return true; // Placeholder for actual initialization logic -} - -/*! - @brief Sets the text size for the display. - @param sz - The size of the text to set. -*/ -void DisplayHardware::setTextSize(uint8_t sz) { - // Placeholder for setting text size on the display TODO -} /*! @brief Gets the name of the display hardware instance. diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 0622c5f11..7317e674f 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -32,21 +32,25 @@ class DisplayHardware { public: DisplayHardware(const char *name); ~DisplayHardware(); - // High-level API functions + + // + // API for configuring the display hardware // + // const char *getName(); void setType(wippersnapper_display_v1_DisplayType type); wippersnapper_display_v1_DisplayType getType(); bool beginEPD(wippersnapper_display_v1_EPDConfig *config, wippersnapper_display_v1_EpdSpiConfig *spi_config); - bool begin(bool reset = true); - // API functions to abstract Adafruit_GFX - void setTextSize(uint8_t sz); + + // + // API for Adafruit_GFX that abstracts hardware functionality + // NOTE: These methods are meant to be implemented within dispDrvBase and exposed within dispDrv driver instances + // + // TODO private: const char *_name; ///< Identifies the hardware instance wippersnapper_display_v1_DisplayType _type; ///< Display type - wippersnapper_display_v1_EPDThinkInkPanel - _thinkink_driver; ///< ThinkInk driver type dispDrvBase *_disp_drv_base = nullptr; ///< Base display driver }; #endif // WS_DISPLAY_HARDWARE_H \ No newline at end of file diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index b0f15a4ad..5c5f8d643 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index c74878946..0cfb40792 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index e0ced97b2..1e88f3178 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -34,4 +34,3 @@ PB_BIND(wippersnapper_display_v1_DisplayRemoved, wippersnapper_display_v1_Displa - diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index fb19c2f75..69d1ae6a4 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -35,12 +35,6 @@ typedef enum _wippersnapper_display_v1_EPDColors { wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW = 7 } wippersnapper_display_v1_EPDColors; -typedef enum _wippersnapper_display_v1_EPDThinkInkPanel { - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED = 0, - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_MFGN = 1, - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_T5 = 2 -} wippersnapper_display_v1_EPDThinkInkPanel; - /* Struct definitions */ typedef struct _wippersnapper_display_v1_DisplayAddedorReplaced { bool did_add; @@ -56,7 +50,6 @@ typedef struct _wippersnapper_display_v1_DisplayRemoved { typedef struct _wippersnapper_display_v1_EPDConfig { wippersnapper_display_v1_EPDMode mode; - wippersnapper_display_v1_EPDThinkInkPanel panel; int32_t width; int32_t height; } wippersnapper_display_v1_EPDConfig; @@ -111,10 +104,6 @@ typedef struct _wippersnapper_display_v1_DisplayWrite { #define _wippersnapper_display_v1_EPDColors_MAX wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW #define _wippersnapper_display_v1_EPDColors_ARRAYSIZE ((wippersnapper_display_v1_EPDColors)(wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW+1)) -#define _wippersnapper_display_v1_EPDThinkInkPanel_MIN wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED -#define _wippersnapper_display_v1_EPDThinkInkPanel_MAX wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_T5 -#define _wippersnapper_display_v1_EPDThinkInkPanel_ARRAYSIZE ((wippersnapper_display_v1_EPDThinkInkPanel)(wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_290_GRAYSCALE4_T5+1)) - #ifdef __cplusplus extern "C" { @@ -122,7 +111,7 @@ extern "C" { /* Initializer values for message structs */ #define wippersnapper_display_v1_EpdSpiConfig_init_default {0, "", "", "", "", ""} -#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN, _wippersnapper_display_v1_EPDThinkInkPanel_MIN, 0, 0} +#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN, 0, 0} #define wippersnapper_display_v1_EPDWriteOptions_init_default {0, _wippersnapper_display_v1_EPDColors_MIN} #define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} #define wippersnapper_display_v1_DisplayRemove_init_default {""} @@ -130,7 +119,7 @@ extern "C" { #define wippersnapper_display_v1_DisplayAddedorReplaced_init_default {0} #define wippersnapper_display_v1_DisplayRemoved_init_default {0} #define wippersnapper_display_v1_EpdSpiConfig_init_zero {0, "", "", "", "", ""} -#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN, _wippersnapper_display_v1_EPDThinkInkPanel_MIN, 0, 0} +#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN, 0, 0} #define wippersnapper_display_v1_EPDWriteOptions_init_zero {0, _wippersnapper_display_v1_EPDColors_MIN} #define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} #define wippersnapper_display_v1_DisplayRemove_init_zero {""} @@ -143,9 +132,8 @@ extern "C" { #define wippersnapper_display_v1_DisplayRemove_name_tag 1 #define wippersnapper_display_v1_DisplayRemoved_did_remove_tag 1 #define wippersnapper_display_v1_EPDConfig_mode_tag 1 -#define wippersnapper_display_v1_EPDConfig_panel_tag 2 -#define wippersnapper_display_v1_EPDConfig_width_tag 3 -#define wippersnapper_display_v1_EPDConfig_height_tag 4 +#define wippersnapper_display_v1_EPDConfig_width_tag 2 +#define wippersnapper_display_v1_EPDConfig_height_tag 3 #define wippersnapper_display_v1_EPDWriteOptions_text_size_tag 1 #define wippersnapper_display_v1_EPDWriteOptions_color_tag 2 #define wippersnapper_display_v1_EpdSpiConfig_bus_tag 1 @@ -175,9 +163,8 @@ X(a, STATIC, SINGULAR, STRING, pin_busy, 6) #define wippersnapper_display_v1_EPDConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, mode, 1) \ -X(a, STATIC, SINGULAR, UENUM, panel, 2) \ -X(a, STATIC, SINGULAR, INT32, width, 3) \ -X(a, STATIC, SINGULAR, INT32, height, 4) +X(a, STATIC, SINGULAR, INT32, width, 2) \ +X(a, STATIC, SINGULAR, INT32, height, 3) #define wippersnapper_display_v1_EPDConfig_CALLBACK NULL #define wippersnapper_display_v1_EPDConfig_DEFAULT NULL @@ -241,9 +228,9 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; /* Maximum encoded size of messages (where known) */ #define wippersnapper_display_v1_EpdSpiConfig_size 46 -#define wippersnapper_display_v1_EPDConfig_size 26 +#define wippersnapper_display_v1_EPDConfig_size 24 #define wippersnapper_display_v1_EPDWriteOptions_size 13 -#define wippersnapper_display_v1_DisplayAddOrReplace_size 143 +#define wippersnapper_display_v1_DisplayAddOrReplace_size 141 #define wippersnapper_display_v1_DisplayRemove_size 7 #define wippersnapper_display_v1_DisplayWrite_size 29 #define wippersnapper_display_v1_DisplayAddedorReplaced_size 2 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index 982aa0c74..c6200ad21 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index 832684805..c0e908f33 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index 4e0b0d556..1e4b8a37d 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index bb436342e..36375187f 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index b36c39da6..c561f5b9c 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index a43271502..2ad5dc5e4 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index ab8eea0ea..7382bd3a5 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index 0185e165f..c9090e070 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index 4064b8e24..ad242e2a7 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index 56d380ed1..c0add168c 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index 19195804d..8b1e357a0 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index 754f4c0dc..2b56dafa3 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index 2c3c348f9..d3ebe5c5d 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 2426bbac1..55f89e858 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED @@ -463,7 +463,7 @@ union wippersnapper_signal_v1_CreateSignalRequest_payload_size_union {char f6[(6 #define wippersnapper_signal_v1_SignalResponse_size 2 #define wippersnapper_signal_v1_PWMRequest_size 82 #define wippersnapper_signal_v1_PWMResponse_size 11 -#define wippersnapper_signal_v1_DisplayRequest_size 146 +#define wippersnapper_signal_v1_DisplayRequest_size 144 #define wippersnapper_signal_v1_DisplayResponse_size 4 #ifdef __cplusplus diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index 7c4c78868..61e2dfcb0 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index 3a9b70fb2..c204458a2 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Aug 15 17:34:50 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From 12d23548e2a4ce99165f22e430c0d00c8ed151e9 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 19 Aug 2025 12:15:55 -0400 Subject: [PATCH 13/76] Route DisplayWrite throughout MVC --- src/Wippersnapper.cpp | 11 +++++ src/components/display/controller.cpp | 28 +++++++++++ src/components/display/controller.h | 3 +- src/components/display/drivers/dispDrvBase.h | 4 +- .../dispDrvThinkInkGrayscale4Eaamfgn.h | 46 +++++++++++++++++++ src/components/display/hardware.cpp | 20 ++++---- src/components/display/hardware.h | 7 +-- 7 files changed, 104 insertions(+), 15 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 3ead64bf3..528d793f3 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -1688,6 +1688,17 @@ bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field, WS._displayController->Handle_Display_AddOrReplace(&msgAddReq); // TODO: Add response handling and publishing here, for now it always // returns true and doesnt publish back to the broker + } else if (field->tag == + wippersnapper_signal_v1_DisplayRequest_display_write_tag) { + // Decode message into a DisplayAddRequest + wippersnapper_display_v1_DisplayWrite msgWrite = + wippersnapper_display_v1_DisplayWrite_init_zero; + if (!ws_pb_decode(stream, wippersnapper_display_v1_DisplayWrite_fields, + &msgWrite)) { + WS_DEBUG_PRINTLN("ERROR: Failure decoding DisplayWrite message!"); + return false; + } + WS._displayController->Handle_Display_Write(&msgWrite); } return true; } diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 1c8e515ea..e583601bb 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -84,4 +84,32 @@ bool DisplayController::Handle_Display_Remove( } WS_DEBUG_PRINTLN("[display] Could not remove display, not found!"); return false; +} + +/*! + @brief Handles a Display_Write message. + @param msgWrite + Pointer to a DisplayWrite message structure. + @return True if the display write was successful, false otherwise. +*/ +bool DisplayController::Handle_Display_Write( + wippersnapper_display_v1_DisplayWrite *msgWrite) { + // Get the driver instance for the display + DisplayHardware *display = nullptr; + for (auto &hw_instance : _hw_instances) { + if (strcmp(hw_instance->getName(), msgWrite->name) == 0) { + display = hw_instance; + break; + } + } + + // Early-out if display not found + if (!display) { + WS_DEBUG_PRINTLN("[display] Failed to write, driver not found!"); + return false; + } + + // Write the message to the display + display->writeMessage(msgWrite->message); + return true; } \ No newline at end of file diff --git a/src/components/display/controller.h b/src/components/display/controller.h index e203ed9de..f4c087e30 100644 --- a/src/components/display/controller.h +++ b/src/components/display/controller.h @@ -34,7 +34,8 @@ class DisplayController { bool Handle_Display_AddOrReplace( wippersnapper_display_v1_DisplayAddOrReplace *msgAdd); bool Handle_Display_Remove(wippersnapper_display_v1_DisplayRemove *msgRemove); - // bool Handle_Display_Write(...); + bool Handle_Display_Write(wippersnapper_display_v1_DisplayWrite *msgWrite); + private: std::vector _hw_instances; ///< Holds pointers to DisplayHardware instances diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index a95c6d7eb..d8eb78796 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -31,15 +31,17 @@ class dispDrvBase { // Destructor implementation (if we need one) }; - // Virtual function to be implemented by derived classes virtual bool begin(thinkinkmode_t mode, bool reset = true); + virtual void writeMessage(const char *message) = 0; + protected: int16_t _pin_dc; int16_t _pin_rst; int16_t _pin_cs; int16_t _pin_busy; int16_t _pin_sram_cs; // for optional EPD SRAM chip select + uint8_t _text_sz = 1; ///< Text size for display messages }; #endif // WS_DISP_DRV_BASE_H \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index 0c347d220..34ccb99d0 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -41,9 +41,55 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { // Clear the display buffer _display->clearBuffer(); _display->display(); + return true; } + virtual void writeMessage(const char *message) override { + if (_display == nullptr) + return; + + // Start with a fresh display buffer + // and settings + int16_t y_idx = 0; + _display->clearDisplay(); + _display->setTextSize(_text_sz); + _display->setTextColor(EPD_BLACK); + _display->setCursor(0, y_idx); + _display->display(); + + // Calculate the line height based on the text size (NOTE: base height is + // 8px) + int16_t line_height = 8 * _text_sz; + uint16_t c_idx = 0; + size_t msg_size = strlen(message); + for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) { + if (message[i] == '\\' && i + 1 < msg_size && + (message[i + 1] == 'n' || message[i + 1] == 'r')) { + // Handle \r\n sequence as a single newline + if (message[i + 1] == 'r' && i + 3 < msg_size && + message[i + 2] == '\\' && message[i + 3] == 'n') { + // Skip to the next line + y_idx += line_height; + _display->setCursor(0, y_idx); + i += 3; + } else if (message[i + 1] == 'n') { + // Skip to the next line + y_idx += line_height; + _display->setCursor(0, y_idx); + i++; + } + } else if (message[i] == 0xC2 && message[i + 1] == 0xB0) { + _display->write(char(248)); + _display->display(); + i++; + } else { + _display->print(message[i]); + _display->display(); + } + } + } + private: ThinkInk_290_Grayscale4_EAAMFGN *_display; }; diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 30fbc24a4..f8f67bdd9 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -105,13 +105,6 @@ bool DisplayHardware::beginEPD( return false; } - // Validate panel type - if (config->panel == - wippersnapper_display_v1_EPDThinkInkPanel_EPD_THINK_INK_PANEL_UNSPECIFIED) { - WS_DEBUG_PRINTLN("[display] Unsupported EPD panel type!"); - return false; // Unsupported panel type - } - // Validate mode is a correct EPD mode if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_UNSPECIFIED) { WS_DEBUG_PRINTLN("[display] Unsupported EPD mode!"); @@ -168,17 +161,24 @@ bool DisplayHardware::beginEPD( if (!_disp_drv_base->begin(epd_mode)) { WS_DEBUG_PRINTLN("[display] Failed to begin display driver!"); - delete _disp_drv_base; // Clean up if initialization failed + delete _disp_drv_base; _disp_drv_base = nullptr; - return false; // Failed to begin display driver + return false; } return true; // Configuration successful } - /*! @brief Gets the name of the display hardware instance. @return The name of the display hardware instance. */ const char *DisplayHardware::getName() { return _name; } + +void DisplayHardware::writeMessage(const char *message) { + if (_disp_drv_base) { + _disp_drv_base->writeMessage(message); + } else { + WS_DEBUG_PRINTLN("[display] No display driver initialized!"); + } +} \ No newline at end of file diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 7317e674f..996d2689c 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -44,13 +44,14 @@ class DisplayHardware { // // API for Adafruit_GFX that abstracts hardware functionality - // NOTE: These methods are meant to be implemented within dispDrvBase and exposed within dispDrv driver instances + // NOTE: These methods are meant to be implemented within dispDrvBase and + // exposed within dispDrv driver instances // - // TODO + void writeMessage(const char *message); private: const char *_name; ///< Identifies the hardware instance wippersnapper_display_v1_DisplayType _type; ///< Display type - dispDrvBase *_disp_drv_base = nullptr; ///< Base display driver + dispDrvBase *_disp_drv_base = nullptr; ///< Base display driver }; #endif // WS_DISPLAY_HARDWARE_H \ No newline at end of file From e8fbd8786c4d3a4a02b807daa38f7b2edb03ca2d Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 19 Aug 2025 15:40:46 -0400 Subject: [PATCH 14/76] Checkin Display Write handler code --- src/Wippersnapper.cpp | 5 +++- src/Wippersnapper_demo.ino.cpp | 26 +++++++++++++++++++ src/components/display/controller.cpp | 5 ++++ .../dispDrvThinkInkGrayscale4Eaamfgn.h | 8 +++--- src/components/display/hardware.cpp | 15 ++++++++--- src/components/display/hardware.h | 2 +- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 4 +-- src/wippersnapper/display/v1/display.pb.h | 12 ++++----- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 4 +-- src/wippersnapper/signal/v1/signal.pb.h | 4 +-- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 26 files changed, 79 insertions(+), 38 deletions(-) create mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 528d793f3..28e74e8c1 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2424,7 +2424,7 @@ bool Wippersnapper::generateWSTopics() { // /display topic // - // Pre-determine topic size +// Pre-determine topic size topicLen = strlen(WS._config.aio_user) + strlen("/") + strlen(_device_uid) + strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + strlen("broker") + strlen(TOPIC_DISPLAY) + 1; @@ -2449,7 +2449,10 @@ bool Wippersnapper::generateWSTopics() { // Subscribe to signal's DISPLAY sub-topic and set callback _topic_signal_display_sub = new Adafruit_MQTT_Subscribe(WS._mqtt, WS._topic_signal_display_brkr, 1); + WS_DEBUG_PRINTLN("Subscribing to DISPLAY topic: "); + WS_DEBUG_PRINTLN(WS._topic_signal_display_brkr); WS._mqtt->subscribe(_topic_signal_display_sub); + WS_DEBUG_PRINTLN("Subscribed to DISPLAY topic!"); _topic_signal_display_sub->setCallback(cbDisplayMessage); // Calculate length of the topic for device-to-broker DISPLAY topic diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp new file mode 100644 index 000000000..cd92237c7 --- /dev/null +++ b/src/Wippersnapper_demo.ino.cpp @@ -0,0 +1,26 @@ +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmplty6x38x" +#include +# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +#include "Wippersnapper_Networking.h" +Wippersnapper_WiFi wipper; + + +#define WS_DEBUG +void setup(); +void loop(); +#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +void setup() { + + wipper.provision(); + + Serial.begin(115200); + + + wipper.connect(); + +} + +void loop() { + wipper.run(); +} \ No newline at end of file diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index e583601bb..d85794c43 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -38,6 +38,8 @@ DisplayController::~DisplayController() { bool DisplayController::Handle_Display_AddOrReplace( wippersnapper_display_v1_DisplayAddOrReplace *msgAdd) { DisplayHardware *display = new DisplayHardware(msgAdd->name); + WS_DEBUG_PRINT("[display] Adding or replacing display: "); + WS_DEBUG_PRINTLN(msgAdd->name); // Configure display type display->setType(msgAdd->type); @@ -97,6 +99,9 @@ bool DisplayController::Handle_Display_Write( // Get the driver instance for the display DisplayHardware *display = nullptr; for (auto &hw_instance : _hw_instances) { + // print hte _hw_instances name + WS_DEBUG_PRINT("[display] Checking hardware instance: "); + WS_DEBUG_PRINTLN(hw_instance->getName()); if (strcmp(hw_instance->getName(), msgWrite->name) == 0) { display = hw_instance; break; diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index 34ccb99d0..adcd849d7 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -1,7 +1,7 @@ /*! * @file src/components/display/drivers/drvDispThinkInkGrayscale4Eaamfgn.h * - * Driver for ThinkInk 2.9" Grayscale 4-level EAAMFGN display (2025 MagTag). + * Driver for ThinkInk 2.9" Grayscale 4-level EAAMFGN display (present on the 2025 version of the Adafruit MagTag) * * Adafruit invests time and resources providing this open source code, * please support Adafruit and open-source hardware by purchasing @@ -41,6 +41,7 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { // Clear the display buffer _display->clearBuffer(); _display->display(); + _text_sz = 3; // Configure default magTag text size return true; } @@ -55,8 +56,8 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { _display->clearDisplay(); _display->setTextSize(_text_sz); _display->setTextColor(EPD_BLACK); + _display->setTextWrap(true); _display->setCursor(0, y_idx); - _display->display(); // Calculate the line height based on the text size (NOTE: base height is // 8px) @@ -81,13 +82,12 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { } } else if (message[i] == 0xC2 && message[i + 1] == 0xB0) { _display->write(char(248)); - _display->display(); i++; } else { _display->print(message[i]); - _display->display(); } } + _display->display(); } private: diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index f8f67bdd9..59a8def95 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -27,7 +27,13 @@ static const std::map FactoryDrvDisp = { [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, int16_t busy) -> dispDrvBase * { return new drvDispThinkInkGrayscale4Eaamfgn(dc, rst, cs, sram_cs, busy); - }}}; + }}, + {"magtag_2025", + [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, + int16_t busy) -> dispDrvBase * { + return new drvDispThinkInkGrayscale4Eaamfgn(dc, rst, cs, sram_cs, busy); + }} + }; /*! @brief Creates a new display driver instance based on the driver name. @@ -50,9 +56,9 @@ dispDrvBase *CreateDrvDisp(const char *driver_name, int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs = -1, int16_t busy = -1) { auto it = FactoryDrvDisp.find(driver_name); - if (it == FactoryDrvDisp.end()) { + if (it == FactoryDrvDisp.end()) return nullptr; - } + return it->second(dc, rst, cs, sram_cs, busy); } @@ -60,7 +66,8 @@ dispDrvBase *CreateDrvDisp(const char *driver_name, int16_t dc, int16_t rst, @brief Constructs a new DisplayHardware object */ DisplayHardware::DisplayHardware(const char *name) { - _name = name; ///< Set the name of the hardware instance + strncpy(_name, name, sizeof(_name) - 1); + _name[sizeof(_name) - 1] = '\0'; _type = wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_UNSPECIFIED; } diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 996d2689c..17c36ee09 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -50,7 +50,7 @@ class DisplayHardware { void writeMessage(const char *message); private: - const char *_name; ///< Identifies the hardware instance + char _name[64]; ///< Identifies the hardware instance wippersnapper_display_v1_DisplayType _type; ///< Display type dispDrvBase *_disp_drv_base = nullptr; ///< Base display driver }; diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index 5c5f8d643..a01de88c0 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index 0cfb40792..9aad63649 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 1e88f3178..48d44bb8a 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -21,7 +21,7 @@ PB_BIND(wippersnapper_display_v1_DisplayAddOrReplace, wippersnapper_display_v1_D PB_BIND(wippersnapper_display_v1_DisplayRemove, wippersnapper_display_v1_DisplayRemove, AUTO) -PB_BIND(wippersnapper_display_v1_DisplayWrite, wippersnapper_display_v1_DisplayWrite, AUTO) +PB_BIND(wippersnapper_display_v1_DisplayWrite, wippersnapper_display_v1_DisplayWrite, 2) PB_BIND(wippersnapper_display_v1_DisplayAddedorReplaced, wippersnapper_display_v1_DisplayAddedorReplaced, AUTO) diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index 69d1ae6a4..69a0aa023 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -41,7 +41,7 @@ typedef struct _wippersnapper_display_v1_DisplayAddedorReplaced { } wippersnapper_display_v1_DisplayAddedorReplaced; typedef struct _wippersnapper_display_v1_DisplayRemove { - char name[6]; + char name[64]; } wippersnapper_display_v1_DisplayRemove; typedef struct _wippersnapper_display_v1_DisplayRemoved { @@ -82,8 +82,8 @@ typedef struct _wippersnapper_display_v1_DisplayAddOrReplace { } wippersnapper_display_v1_DisplayAddOrReplace; typedef struct _wippersnapper_display_v1_DisplayWrite { - char name[6]; - char message[6]; + char name[64]; + char message[1024]; pb_size_t which_options; union { wippersnapper_display_v1_EPDWriteOptions epd_options; @@ -231,8 +231,8 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; #define wippersnapper_display_v1_EPDConfig_size 24 #define wippersnapper_display_v1_EPDWriteOptions_size 13 #define wippersnapper_display_v1_DisplayAddOrReplace_size 141 -#define wippersnapper_display_v1_DisplayRemove_size 7 -#define wippersnapper_display_v1_DisplayWrite_size 29 +#define wippersnapper_display_v1_DisplayRemove_size 65 +#define wippersnapper_display_v1_DisplayWrite_size 1106 #define wippersnapper_display_v1_DisplayAddedorReplaced_size 2 #define wippersnapper_display_v1_DisplayRemoved_size 2 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index c6200ad21..f95f752af 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index c0e908f33..112240f45 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index 1e4b8a37d..88153e9d5 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 36375187f..5d2523e83 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index c561f5b9c..2aee561ac 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index 2ad5dc5e4..5b635d492 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index 7382bd3a5..d6beb4b79 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index c9090e070..72e885682 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index ad242e2a7..5649c2dd8 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index c0add168c..5b26ce7eb 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index 8b1e357a0..e012bc73f 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index 2b56dafa3..e285c9957 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index d3ebe5c5d..d4c6687bf 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -48,7 +48,7 @@ PB_BIND(wippersnapper_signal_v1_PWMRequest, wippersnapper_signal_v1_PWMRequest, PB_BIND(wippersnapper_signal_v1_PWMResponse, wippersnapper_signal_v1_PWMResponse, AUTO) -PB_BIND(wippersnapper_signal_v1_DisplayRequest, wippersnapper_signal_v1_DisplayRequest, AUTO) +PB_BIND(wippersnapper_signal_v1_DisplayRequest, wippersnapper_signal_v1_DisplayRequest, 2) PB_BIND(wippersnapper_signal_v1_DisplayResponse, wippersnapper_signal_v1_DisplayResponse, AUTO) diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 55f89e858..2a0997d57 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED @@ -463,7 +463,7 @@ union wippersnapper_signal_v1_CreateSignalRequest_payload_size_union {char f6[(6 #define wippersnapper_signal_v1_SignalResponse_size 2 #define wippersnapper_signal_v1_PWMRequest_size 82 #define wippersnapper_signal_v1_PWMResponse_size 11 -#define wippersnapper_signal_v1_DisplayRequest_size 144 +#define wippersnapper_signal_v1_DisplayRequest_size 1109 #define wippersnapper_signal_v1_DisplayResponse_size 4 #ifdef __cplusplus diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index 61e2dfcb0..c81b97eee 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index c204458a2..4e7fa2a39 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 18 18:41:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From cfb893d7baef1bd7da7eed6e5e97616871d0f41c Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 19 Aug 2025 16:46:22 -0400 Subject: [PATCH 15/76] debugging failed to subscribe err --- src/Wippersnapper.cpp | 29 ++++++++++++++----- src/Wippersnapper_demo.ino.cpp | 2 +- .../dispDrvThinkInkGrayscale4Eaamfgn.h | 3 +- src/components/display/hardware.cpp | 3 +- 4 files changed, 25 insertions(+), 12 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 28e74e8c1..c193ec277 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2424,7 +2424,7 @@ bool Wippersnapper::generateWSTopics() { // /display topic // -// Pre-determine topic size + // Pre-determine topic size topicLen = strlen(WS._config.aio_user) + strlen("/") + strlen(_device_uid) + strlen("/wprsnpr/") + strlen(TOPIC_SIGNALS) + strlen("broker") + strlen(TOPIC_DISPLAY) + 1; @@ -2942,6 +2942,26 @@ void Wippersnapper::connect() { haltError("Unable to allocate space for MQTT error topics"); } + // TODO: We are debugging the "Failed to subscribe" issue here prior to + // runNetFSM Print out all topics generated by generateWSTopics() + WS_DEBUG_PRINTLN("MQTT Topics:"); + WS_DEBUG_PRINT(" Device UID: "); + WS_DEBUG_PRINTLN(_device_uid); + // Broker topics only + WS_DEBUG_PRINT(" Broker-to-Device DS18x20 Topic: "); + WS_DEBUG_PRINTLN(WS._topic_signal_ds18_device); + WS_DEBUG_PRINT(" Broker-to-Device Servo Topic: "); + WS_DEBUG_PRINTLN(WS._topic_signal_servo_device); + WS_DEBUG_PRINT(" Broker-to-Device PWM Topic: "); + WS_DEBUG_PRINTLN(WS._topic_signal_pwm_device); + WS_DEBUG_PRINT(" Broker-to-Device Pixels Topic: "); + WS_DEBUG_PRINTLN(WS._topic_signal_pixels_device); + WS_DEBUG_PRINT(" Broker-to-Device UART Topic: "); + WS_DEBUG_PRINTLN(WS._topic_signal_uart_device); + WS_DEBUG_PRINT(" Broker-to-Device Display Topic: "); + WS_DEBUG_PRINTLN(WS._topic_signal_display_device); + delay(500); + // Connect to Network WS_DEBUG_PRINTLN("Running Network FSM..."); // Run the network fsm @@ -2994,13 +3014,6 @@ void Wippersnapper::connect() { statusLEDFade(GREEN, 3); WS_DEBUG_PRINTLN( "Registration and configuration complete!\nRunning application..."); - - // Print out display topics - WS_DEBUG_PRINTLN("Device-to-Broker DISPLAY topic: "); - WS_DEBUG_PRINTLN(WS._topic_signal_display_device); - WS_DEBUG_PRINTLN("Broker-to-Device DISPLAY topic: "); - WS_DEBUG_PRINTLN(WS._topic_signal_display_brkr); - delay(500); } /**************************************************************************/ diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp index cd92237c7..82b309dfd 100644 --- a/src/Wippersnapper_demo.ino.cpp +++ b/src/Wippersnapper_demo.ino.cpp @@ -1,4 +1,4 @@ -# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmplty6x38x" +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpbebqve76" #include # 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" # 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index adcd849d7..0ccb1b7d8 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -1,7 +1,8 @@ /*! * @file src/components/display/drivers/drvDispThinkInkGrayscale4Eaamfgn.h * - * Driver for ThinkInk 2.9" Grayscale 4-level EAAMFGN display (present on the 2025 version of the Adafruit MagTag) + * Driver for ThinkInk 2.9" Grayscale 4-level EAAMFGN display (present on the + * 2025 version of the Adafruit MagTag) * * Adafruit invests time and resources providing this open source code, * please support Adafruit and open-source hardware by purchasing diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 59a8def95..131c8ba8e 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -32,8 +32,7 @@ static const std::map FactoryDrvDisp = { [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, int16_t busy) -> dispDrvBase * { return new drvDispThinkInkGrayscale4Eaamfgn(dc, rst, cs, sram_cs, busy); - }} - }; + }}}; /*! @brief Creates a new display driver instance based on the driver name. From 024237309654af01a8fcce6d4232180803e9719d Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 20 Aug 2025 10:48:20 -0400 Subject: [PATCH 16/76] Speed up writeMessage --- src/Wippersnapper.cpp | 20 ------------------- src/Wippersnapper_demo.ino.cpp | 2 +- src/components/display/controller.cpp | 5 ++--- .../dispDrvThinkInkGrayscale4Eaamfgn.h | 12 +++++------ 4 files changed, 9 insertions(+), 30 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index c193ec277..17b19a3c1 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2942,26 +2942,6 @@ void Wippersnapper::connect() { haltError("Unable to allocate space for MQTT error topics"); } - // TODO: We are debugging the "Failed to subscribe" issue here prior to - // runNetFSM Print out all topics generated by generateWSTopics() - WS_DEBUG_PRINTLN("MQTT Topics:"); - WS_DEBUG_PRINT(" Device UID: "); - WS_DEBUG_PRINTLN(_device_uid); - // Broker topics only - WS_DEBUG_PRINT(" Broker-to-Device DS18x20 Topic: "); - WS_DEBUG_PRINTLN(WS._topic_signal_ds18_device); - WS_DEBUG_PRINT(" Broker-to-Device Servo Topic: "); - WS_DEBUG_PRINTLN(WS._topic_signal_servo_device); - WS_DEBUG_PRINT(" Broker-to-Device PWM Topic: "); - WS_DEBUG_PRINTLN(WS._topic_signal_pwm_device); - WS_DEBUG_PRINT(" Broker-to-Device Pixels Topic: "); - WS_DEBUG_PRINTLN(WS._topic_signal_pixels_device); - WS_DEBUG_PRINT(" Broker-to-Device UART Topic: "); - WS_DEBUG_PRINTLN(WS._topic_signal_uart_device); - WS_DEBUG_PRINT(" Broker-to-Device Display Topic: "); - WS_DEBUG_PRINTLN(WS._topic_signal_display_device); - delay(500); - // Connect to Network WS_DEBUG_PRINTLN("Running Network FSM..."); // Run the network fsm diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp index 82b309dfd..68e2f7f00 100644 --- a/src/Wippersnapper_demo.ino.cpp +++ b/src/Wippersnapper_demo.ino.cpp @@ -1,4 +1,4 @@ -# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpbebqve76" +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpnv6_o84f" #include # 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" # 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index d85794c43..a80adf0ed 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -99,9 +99,6 @@ bool DisplayController::Handle_Display_Write( // Get the driver instance for the display DisplayHardware *display = nullptr; for (auto &hw_instance : _hw_instances) { - // print hte _hw_instances name - WS_DEBUG_PRINT("[display] Checking hardware instance: "); - WS_DEBUG_PRINTLN(hw_instance->getName()); if (strcmp(hw_instance->getName(), msgWrite->name) == 0) { display = hw_instance; break; @@ -115,6 +112,8 @@ bool DisplayController::Handle_Display_Write( } // Write the message to the display + WS_DEBUG_PRINT("[display] Writing message to display: "); + WS_DEBUG_PRINTLN(msgWrite->message); display->writeMessage(msgWrite->message); return true; } \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index 0ccb1b7d8..9c9f4d027 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -39,10 +39,14 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { // Initialize the display _display->begin(mode); + // Configure display settings + _text_sz = 3; + _display->setTextSize(_text_sz); + _display->setTextColor(EPD_BLACK); + _display->setTextWrap(false); // Clear the display buffer _display->clearBuffer(); _display->display(); - _text_sz = 3; // Configure default magTag text size return true; } @@ -52,12 +56,8 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { return; // Start with a fresh display buffer - // and settings + _display->clearBuffer(); int16_t y_idx = 0; - _display->clearDisplay(); - _display->setTextSize(_text_sz); - _display->setTextColor(EPD_BLACK); - _display->setTextWrap(true); _display->setCursor(0, y_idx); // Calculate the line height based on the text size (NOTE: base height is From b5e53344d8f8fdc58c56e43327fe71430f078c72 Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 20 Aug 2025 13:21:00 -0400 Subject: [PATCH 17/76] Doxygen across new sections --- .gitignore | 4 +- src/Wippersnapper.h | 38 ++++++++---- src/Wippersnapper_demo.ino.cpp | 26 -------- src/components/display/drivers/dispDrvBase.h | 59 +++++++++++++++---- .../dispDrvThinkInkGrayscale4Eaamfgn.h | 43 +++++++++++++- src/components/display/hardware.cpp | 26 +++++--- src/components/display/hardware.h | 4 +- 7 files changed, 136 insertions(+), 64 deletions(-) delete mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/.gitignore b/.gitignore index 1caed0bc6..a20a9d40f 100644 --- a/.gitignore +++ b/.gitignore @@ -52,4 +52,6 @@ data/ # Misc. Data tests/ -venv/ \ No newline at end of file +venv/ + +Doxyfile \ No newline at end of file diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 654fd4c66..758e97f2d 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -47,16 +47,24 @@ // Define actual debug output functions when necessary. #ifdef WS_DEBUG #define WS_DEBUG_PRINT(...) \ - { WS_PRINTER.print(__VA_ARGS__); } ///< Prints debug output. + { \ + WS_PRINTER.print(__VA_ARGS__); \ + } ///< Prints debug output. #define WS_DEBUG_PRINTLN(...) \ - { WS_PRINTER.println(__VA_ARGS__); } ///< Prints line from debug output. + { \ + WS_PRINTER.println(__VA_ARGS__); \ + } ///< Prints line from debug output. #define WS_DEBUG_PRINTHEX(...) \ - { WS_PRINTER.print(__VA_ARGS__, HEX); } ///< Prints debug output. + { \ + WS_PRINTER.print(__VA_ARGS__, HEX); \ + } ///< Prints debug output. #else #define WS_DEBUG_PRINT(...) \ - {} ///< Prints debug output + { \ + } ///< Prints debug output #define WS_DEBUG_PRINTLN(...) \ - {} ///< Prints line from debug output. + { \ + } ///< Prints line from debug output. #endif #define WS_DELAY_WITH_WDT(timeout) \ @@ -127,12 +135,12 @@ #include "display/ws_display_ui_helper.h" #endif +#include "components/display/controller.h" #include "components/ds18x20/ws_ds18x20.h" #include "components/pixels/ws_pixels.h" #include "components/pwm/ws_pwm.h" #include "components/servo/ws_servo.h" #include "components/uart/ws_uart.h" -#include "components/display/controller.h" #if defined(USE_TINYUSB) #include "provisioning/tinyusb/Wippersnapper_FS.h" @@ -154,7 +162,7 @@ #define TOPIC_INFO "/info/" ///< Registration sub-topic #define TOPIC_SIGNALS "/signals/" ///< Signals sub-topic #define TOPIC_I2C "/i2c" ///< I2C sub-topic -#define TOPIC_DISPLAY "/display" ///< Display sub-topic (EPD, OLED, TFT, etc.) +#define TOPIC_DISPLAY "/display" ///< Display sub-topic (EPD, OLED, TFT, etc.) #define MQTT_TOPIC_PIXELS_DEVICE \ "/signals/device/pixel" ///< Pixels device->broker topic #define MQTT_TOPIC_PIXELS_BROKER \ @@ -371,7 +379,8 @@ class Wippersnapper { ws_servo *_servoComponent; ///< Instance of servo class ws_ds18x20 *_ds18x20Component; ///< Instance of DS18x20 class ws_uart *_uartComponent; ///< Instance of UART class - DisplayController *_displayController; ///< Instance of display controller class + DisplayController + *_displayController; ///< Instance of display controller class // TODO: does this really need to be global? uint8_t _macAddr[6]; /*!< Unique network iface identifier */ @@ -408,8 +417,10 @@ class Wippersnapper { char *_topic_signal_pixels_device = NULL; /*!< Topic carries pixel messages */ char *_topic_signal_uart_brkr = NULL; /*!< Topic carries UART messages */ char *_topic_signal_uart_device = NULL; /*!< Topic carries UART messages */ - char *_topic_signal_display_brkr = NULL; /*!< Topic carries messages from a device to a broker. */ - char *_topic_signal_display_device = NULL; /*!< Topic carries messages from a broker to a device. */ + char *_topic_signal_display_brkr = + NULL; /*!< Topic carries messages from a device to a broker. */ + char *_topic_signal_display_device = + NULL; /*!< Topic carries messages from a broker to a device. */ wippersnapper_signal_v1_CreateSignalRequest _incomingSignalMsg; /*!< Incoming signal message from broker */ @@ -436,7 +447,8 @@ class Wippersnapper { wippersnapper_signal_v1_UARTRequest msgSignalUART; ///< UARTReq wrapper message - wippersnapper_signal_v1_DisplayRequest msgSignalDisplay; + wippersnapper_signal_v1_DisplayRequest + msgSignalDisplay; ///< DisplayRequest wrapper message char *throttleMessage; /*!< Pointer to throttle message data. */ int throttleTime; /*!< Total amount of time to throttle the device, in @@ -498,8 +510,8 @@ class Wippersnapper { *_topic_signal_pixels_sub; /*!< Subscribes to pixel device topic. */ Adafruit_MQTT_Subscribe *_topic_signal_uart_sub; /*!< Subscribes to signal's UART topic. */ - Adafruit_MQTT_Subscribe - *_topic_signal_display_sub; /*!< Subscription callback for display topic. */ + Adafruit_MQTT_Subscribe *_topic_signal_display_sub; /*!< Subscription callback + for display topic. */ Adafruit_MQTT_Subscribe *_err_sub; /*!< Subscription to Adafruit IO Error topic. */ diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp deleted file mode 100644 index 68e2f7f00..000000000 --- a/src/Wippersnapper_demo.ino.cpp +++ /dev/null @@ -1,26 +0,0 @@ -# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpnv6_o84f" -#include -# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -#include "Wippersnapper_Networking.h" -Wippersnapper_WiFi wipper; - - -#define WS_DEBUG -void setup(); -void loop(); -#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -void setup() { - - wipper.provision(); - - Serial.begin(115200); - - - wipper.connect(); - -} - -void loop() { - wipper.run(); -} \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index d8eb78796..c7d624836 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -18,30 +18,65 @@ #include "Adafruit_ThinkInk.h" #include "Wippersnapper.h" +/*! + @brief Abstract base class for display drivers. + This class provides a common interface for all display drivers, + allowing them to be used interchangeably. +*/ class dispDrvBase { public: + /*! + @brief Constructor for the base display driver for E-Ink displays. + @param dc + Data/Command pin for the display. + @param rst + Reset pin for the display. + @param cs + Chip Select pin for the display. + @param sram_cs + Optional SRAM Chip Select pin for E-Ink displays that support it. + @param busy + Optional Busy pin for the display. + */ dispDrvBase(int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs = -1, int16_t busy = -1) : _pin_dc(dc), _pin_rst(rst), _pin_cs(cs), _pin_sram_cs(sram_cs), - _pin_busy(busy) { - // Constructor implementation (if we need one) - } + _pin_busy(busy) {} - virtual ~dispDrvBase() { - // Destructor implementation (if we need one) - }; + /*! + @brief Destructor for the base display driver. + This destructor is virtual to allow derived classes to clean up + resources properly. + */ + virtual ~dispDrvBase() {} + /*! + @brief Attempts to initialize a ThinkInk EPD driver. + @param mode + The ThinkInk mode to use for the display. + @param reset + Whether to reset the display before initialization. + @return True if the display was initialized successfully, false otherwise. + */ virtual bool begin(thinkinkmode_t mode, bool reset = true); + /*! + @brief Writes a message to the display. + @param message + The message to write to the display. + @note MUST be implemented by derived classes. + */ virtual void writeMessage(const char *message) = 0; protected: - int16_t _pin_dc; - int16_t _pin_rst; - int16_t _pin_cs; - int16_t _pin_busy; - int16_t _pin_sram_cs; // for optional EPD SRAM chip select - uint8_t _text_sz = 1; ///< Text size for display messages + int16_t _pin_dc; ///< Data/Command pin + int16_t _pin_rst; ///< Reset pin + int16_t _pin_cs; ///< Chip Select pin + int16_t _pin_busy; ///< Optional Busy pin + int16_t _pin_sram_cs; ///< Optional EPD SRAM chip select pin + uint8_t _text_sz = 1; ///< Text size for displaying a message + int16_t _height; ///< Height of the display + int16_t _width; ///< Width of the display }; #endif // WS_DISP_DRV_BASE_H \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index 9c9f4d027..6fcbb1cfe 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -1,5 +1,5 @@ /*! - * @file src/components/display/drivers/drvDispThinkInkGrayscale4Eaamfgn.h + * @file src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h * * Driver for ThinkInk 2.9" Grayscale 4-level EAAMFGN display (present on the * 2025 version of the Adafruit MagTag) @@ -18,8 +18,25 @@ #include "dispDrvBase.h" +/*! + @brief Driver for a ThinkInk 2.9" Grayscale 4-level EAAMFGN display. +*/ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { public: + /*! + @brief Constructor for the ThinkInk Grayscale 4-level EAAMFGN display + driver. + @param dc + Data/Command pin for the display. + @param rst + Reset pin for the display. + @param cs + Chip Select pin for the display. + @param sram_cs + Optional SRAM Chip Select pin for E-Ink displays that support it. + @param busy + Optional Busy pin for the display. + */ drvDispThinkInkGrayscale4Eaamfgn(int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs = -1, int16_t busy = -1) : dispDrvBase(dc, rst, cs, sram_cs, busy), _display(nullptr) {} @@ -31,6 +48,15 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { } } + /*! + @brief Attempts to initialize the ThinkInk Grayscale 4-level EAAMFGN + display driver. + @param mode + The ThinkInk mode to use for the display. + @param reset + Whether to reset the display before initialization. + @return True if the display was initialized successfully, false otherwise. + */ bool begin(thinkinkmode_t mode, bool reset = true) override { _display = new ThinkInk_290_Grayscale4_EAAMFGN(_pin_dc, _pin_rst, _pin_cs, _pin_sram_cs, _pin_busy); @@ -44,6 +70,8 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { _display->setTextSize(_text_sz); _display->setTextColor(EPD_BLACK); _display->setTextWrap(false); + _height = _display->height(); + _width = _display->width(); // Clear the display buffer _display->clearBuffer(); _display->display(); @@ -51,6 +79,13 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { return true; } + /*! + @brief Writes a message to the display. + @param message + The message to write to the display. + @note This method overrides the base class method to provide specific + functionality for the Think Ink Grayscale 4 EAAMGFGN driver. + */ virtual void writeMessage(const char *message) override { if (_display == nullptr) return; @@ -66,17 +101,23 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { uint16_t c_idx = 0; size_t msg_size = strlen(message); for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) { + if (y_idx + line_height > _height) + break; if (message[i] == '\\' && i + 1 < msg_size && (message[i + 1] == 'n' || message[i + 1] == 'r')) { // Handle \r\n sequence as a single newline if (message[i + 1] == 'r' && i + 3 < msg_size && message[i + 2] == '\\' && message[i + 3] == 'n') { // Skip to the next line + if (y_idx + line_height > _height) + break; y_idx += line_height; _display->setCursor(0, y_idx); i += 3; } else if (message[i + 1] == 'n') { // Skip to the next line + if (y_idx + line_height > _height) + break; y_idx += line_height; _display->setCursor(0, y_idx); i++; diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 131c8ba8e..7a67a3dc0 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -63,6 +63,8 @@ dispDrvBase *CreateDrvDisp(const char *driver_name, int16_t dc, int16_t rst, /*! @brief Constructs a new DisplayHardware object + @param name + The name of the hardware instance. */ DisplayHardware::DisplayHardware(const char *name) { strncpy(_name, name, sizeof(_name) - 1); @@ -74,7 +76,10 @@ DisplayHardware::DisplayHardware(const char *name) { @brief Destructor */ DisplayHardware::~DisplayHardware() { - // TODO + if (_drvDisp) { + delete _drvDisp; + _drvDisp = nullptr; + } } /*! @@ -152,8 +157,8 @@ bool DisplayHardware::beginEPD( // TODO: Configure SPI bus selection (UNUSED AS OF RIGHT NOW) // Create display driver object using the factory function - _disp_drv_base = CreateDrvDisp(_name, dc, rst, cs, srcs, busy); - if (!_disp_drv_base) { + _drvDisp = CreateDrvDisp(_name, dc, rst, cs, srcs, busy); + if (!_drvDisp) { WS_DEBUG_PRINTLN("[display] Failed to create display driver!"); return false; // Failed to create display driver } @@ -165,10 +170,10 @@ bool DisplayHardware::beginEPD( WS_DEBUG_PRINTLN("[display] EPD mode: GRAYSCALE4"); } - if (!_disp_drv_base->begin(epd_mode)) { + if (!_drvDisp->begin(epd_mode)) { WS_DEBUG_PRINTLN("[display] Failed to begin display driver!"); - delete _disp_drv_base; - _disp_drv_base = nullptr; + delete _drvDisp; + _drvDisp = nullptr; return false; } @@ -181,9 +186,14 @@ bool DisplayHardware::beginEPD( */ const char *DisplayHardware::getName() { return _name; } +/*! + @brief Writes a message to the display. + @param message + The message to display. +*/ void DisplayHardware::writeMessage(const char *message) { - if (_disp_drv_base) { - _disp_drv_base->writeMessage(message); + if (_drvDisp) { + _drvDisp->writeMessage(message); } else { WS_DEBUG_PRINTLN("[display] No display driver initialized!"); } diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 17c36ee09..570b2e1b8 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -20,14 +20,12 @@ #include #include -/**************************************************************************/ /*! @brief Interface for interacting with display hardware (TFT, eInk, OLED, etc.) This class provides methods to initialize, write to, and manage the state of display hardware. */ -/**************************************************************************/ class DisplayHardware { public: DisplayHardware(const char *name); @@ -52,6 +50,6 @@ class DisplayHardware { private: char _name[64]; ///< Identifies the hardware instance wippersnapper_display_v1_DisplayType _type; ///< Display type - dispDrvBase *_disp_drv_base = nullptr; ///< Base display driver + dispDrvBase *_drvDisp = nullptr; ///< Base display driver }; #endif // WS_DISPLAY_HARDWARE_H \ No newline at end of file From 05db09227b499ab6ec420b98238d6cdf11e550eb Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 20 Aug 2025 15:42:27 -0400 Subject: [PATCH 18/76] Implement publishing back to IO, T5 driver for pre-2025 --- Doxyfile | 1205 ++++++++++++----- src/Wippersnapper.cpp | 44 +- src/components/display/controller.cpp | 6 +- src/components/display/controller.h | 1 - src/components/display/drivers/dispDrvBase.h | 2 +- .../drivers/dispDrvThinkInkGrayscale4T5.h | 139 ++ src/components/display/hardware.cpp | 19 +- src/components/display/hardware.h | 5 +- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 2 +- src/wippersnapper/display/v1/display.pb.h | 44 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 4 +- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 28 files changed, 1079 insertions(+), 426 deletions(-) create mode 100644 src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h diff --git a/Doxyfile b/Doxyfile index c05228416..3de8ed0d8 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,7 +1,7 @@ -# Doxyfile 1.9.1 +# Doxyfile 1.14.0 # This file describes the settings to be used by the documentation system -# doxygen (www.doxygen.org) for a project. +# Doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. @@ -12,6 +12,16 @@ # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). +# +# Note: +# +# Use Doxygen to compare the used configuration file with the template +# configuration file: +# doxygen -x [configFile] +# Use Doxygen to compare the used configuration file with the template +# configuration file without replacing the environment variables or CMake type +# replacement variables: +# doxygen -x_noenv [configFile] #--------------------------------------------------------------------------- # Project related configuration options @@ -41,7 +51,7 @@ PROJECT_NAME = "Adafruit Library" PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer a +# for a project that appears at the top of each page and should give viewers a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = @@ -53,24 +63,42 @@ PROJECT_BRIEF = PROJECT_LOGO = +# With the PROJECT_ICON tag one can specify an icon that is included in the tabs +# when the HTML document is shown. Doxygen will copy the logo to the output +# directory. + +PROJECT_ICON = + # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where doxygen was started. If +# entered, it will be relative to the location where Doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = -# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- -# directories (in 2 levels) under the output directory of each output format and -# will distribute the generated files over these directories. Enabling this -# option can be useful when feeding doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise causes -# performance problems for the file system. +# If the CREATE_SUBDIRS tag is set to YES then Doxygen will create up to 4096 +# sub-directories (in 2 levels) under the output directory of each output format +# and will distribute the generated files over these directories. Enabling this +# option can be useful when feeding Doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise cause +# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to +# control the number of sub-directories. # The default value is: NO. CREATE_SUBDIRS = NO -# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# Controls the number of sub-directories that will be created when +# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every +# level increment doubles the number of directories, resulting in 4096 +# directories at level 8 which is the default and also the maximum value. The +# sub-directories are organized in 2 levels, the first level always has a fixed +# number of 16 directories. +# Minimum value: 0, maximum value: 8, default value: 8. +# This tag requires that the tag CREATE_SUBDIRS is set to YES. + +CREATE_SUBDIRS_LEVEL = 8 + +# If the ALLOW_UNICODE_NAMES tag is set to YES, Doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. @@ -79,28 +107,28 @@ CREATE_SUBDIRS = NO ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by doxygen is written. Doxygen will use this +# documentation generated by Doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, -# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), -# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, -# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), -# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, -# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, -# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, -# Ukrainian and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, +# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English +# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, +# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with +# English messages), Korean, Korean-en (Korean with English messages), Latvian, +# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, +# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, +# Swedish, Turkish, Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# If the BRIEF_MEMBER_DESC tag is set to YES, Doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# If the REPEAT_BRIEF tag is set to YES, Doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the @@ -131,13 +159,13 @@ ABBREVIATE_BRIEF = "The $name class" \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# doxygen will generate a detailed section even if there is only a brief +# Doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO -# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# If the INLINE_INHERITED_MEMB tag is set to YES, Doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. @@ -145,7 +173,7 @@ ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# If the FULL_PATH_NAMES tag is set to YES, Doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. @@ -155,11 +183,11 @@ FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the path to +# If left blank the directory from which Doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where doxygen is started. +# will be relative from the directory where Doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = @@ -173,31 +201,42 @@ STRIP_FROM_PATH = STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but -# less readable) file names. This can be useful is your file systems doesn't +# If the SHORT_NAMES tag is set to YES, Doxygen will generate much shorter (but +# less readable) file names. This can be useful if your file system doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the -# first line (until the first dot) of a Javadoc-style comment as the brief -# description. If set to NO, the Javadoc-style will behave just like regular Qt- -# style comments (thus requiring an explicit @brief command for a brief -# description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen will interpret the +# first line (until the first dot, question mark or exclamation mark) of a +# Javadoc-style comment as the brief description. If set to NO, the Javadoc- +# style will behave just like regular Qt-style comments (thus requiring an +# explicit @brief command for a brief description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO -# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first -# line (until the first dot) of a Qt-style comment as the brief description. If -# set to NO, the Qt-style will behave just like regular Qt-style comments (thus -# requiring an explicit \brief command for a brief description.) +# If the JAVADOC_BANNER tag is set to YES then Doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by Doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then Doxygen will interpret the first +# line (until the first dot, question mark or exclamation mark) of a Qt-style +# comment as the brief description. If set to NO, the Qt-style will behave just +# like regular Qt-style comments (thus requiring an explicit \brief command for +# a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this @@ -209,13 +248,21 @@ QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO +# By default Python docstrings are displayed as preformatted text and Doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# Doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as Doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# If the SEPARATE_MEMBER_PAGES tag is set to YES then Doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. @@ -232,16 +279,16 @@ TAB_SIZE = 4 # the documentation. An alias has the form: # name=value # For example adding -# "sideeffect=@par Side Effects:\n" +# "sideeffect=@par Side Effects:^^" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". You can put \n's in the value part of an alias to insert -# newlines (in the resulting output). You can put ^^ in the value part of an -# alias to insert a newline as if a physical newline was in the original file. -# When you need a literal { or } or , in the value part of an alias you have to -# escape them by means of a backslash (\), this can lead to conflicts with the -# commands \{ and \} for these it is advised to use the version @{ and @} or use -# a double escape (\\{ and \\}) +# "Side Effects:". Note that you cannot put \n's in the value part of an alias +# to insert newlines (in the resulting output). You can put ^^ in the value part +# of an alias to insert a newline as if a physical newline was in the original +# file. When you need a literal { or } or , in the value part of an alias you +# have to escape them by means of a backslash (\), this can lead to conflicts +# with the commands \{ and \} for these it is advised to use the version @{ and +# @} or use a double escape (\\{ and \\}) ALIASES = @@ -273,34 +320,42 @@ OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, -# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, -# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# language is one of the parsers supported by Doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, +# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the -# default for Fortran type files). For instance to make doxygen treat .inc files +# default for Fortran type files). For instance to make Doxygen treat .inc files # as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by doxygen. When specifying no_extension you should add +# the files are not read by Doxygen. When specifying no_extension you should add # * to the FILE_PATTERNS. # # Note see also the list of default file extension mappings. EXTENSION_MAPPING = -# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# If the MARKDOWN_SUPPORT tag is enabled then Doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See https://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you can -# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# The output of markdown processing is further processed by Doxygen, so you can +# mix Doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. @@ -310,25 +365,45 @@ MARKDOWN_SUPPORT = YES # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 5. +# Minimum value: 0, maximum value: 99, default value: 6. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 0 -# When enabled doxygen tries to link words that correspond to documented +# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to +# generate identifiers for the Markdown headings. Note: Every identifier is +# unique. +# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a +# sequence number starting at 0 and GITHUB use the lower case version of title +# with any whitespace replaced by '-' and punctuation characters removed. +# The default value is: DOXYGEN. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +MARKDOWN_ID_STYLE = DOXYGEN + +# When enabled Doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. +# globally by setting AUTOLINK_SUPPORT to NO. Words listed in the +# AUTOLINK_IGNORE_WORDS tag are excluded from automatic linking. # The default value is: YES. AUTOLINK_SUPPORT = YES +# This tag specifies a list of words that, when matching the start of a word in +# the documentation, will suppress auto links generation, if it is enabled via +# AUTOLINK_SUPPORT. This list does not affect links explicitly created using \# +# or the \link or commands. +# This tag requires that the tag AUTOLINK_SUPPORT is set to YES. + +AUTOLINK_IGNORE_WORDS = + # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let doxygen match functions declarations and +# tag to YES in order to let Doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also make the inheritance and collaboration -# diagrams that involve STL classes more complete and accurate. +# versus func(std::string) {}). This also makes the inheritance and +# collaboration diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO @@ -340,16 +415,16 @@ BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen -# will parse them like normal C++ but will assume all classes use public instead -# of private inheritance when no explicit protection keyword is present. +# https://www.riverbankcomputing.com/software) sources only. Doxygen will parse +# them like normal C++ but will assume all classes use public instead of private +# inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make -# doxygen to replace the get and set methods by a property in the documentation. +# Doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. @@ -358,7 +433,7 @@ SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES then doxygen will reuse the documentation of the first +# tag is set to YES then Doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. @@ -416,21 +491,42 @@ TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the -# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# doxygen will become slower. If the cache is too large, memory is wasted. The +# code, Doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# Doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run doxygen will report the cache usage and suggest +# symbols. At the end of a run Doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 +# The NUM_PROC_THREADS specifies the number of threads Doxygen is allowed to use +# during processing. When set to 0 Doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which effectively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +# If the TIMESTAMP tag is set different from NO then each generated page will +# contain the date or date and time when the page was generated. Setting this to +# NO can help when comparing the output of multiple runs. +# Possible values are: YES, NO, DATETIME and DATE. +# The default value is: NO. + +TIMESTAMP = NO + #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# If the EXTRACT_ALL tag is set to YES, Doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. @@ -446,6 +542,12 @@ EXTRACT_ALL = NO EXTRACT_PRIVATE = NO +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. @@ -483,7 +585,14 @@ EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. @@ -491,22 +600,31 @@ EXTRACT_ANON_NSPACES = NO HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option -# has no effect if EXTRACT_ALL is enabled. +# will also hide undocumented C++ concepts if enabled. This option has no effect +# if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# If the HIDE_UNDOC_NAMESPACES tag is set to YES, Doxygen will hide all +# undocumented namespaces that are normally visible in the namespace hierarchy. +# If set to NO, these namespaces will be included in the various overviews. This +# option has no effect if EXTRACT_ALL is enabled. +# The default value is: YES. + +HIDE_UNDOC_NAMESPACES = YES + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all friend # declarations. If set to NO, these declarations will be included in the # documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. @@ -520,37 +638,44 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO -# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# With the correct setting of option CASE_SENSE_NAMES Doxygen will better be # able to match the capabilities of the underlying filesystem. In case the # filesystem is case sensitive (i.e. it supports files in the same directory # whose names only differ in casing), the option must be set to YES to properly # deal with such files in case they appear in the input. For filesystems that -# are not case sensitive the option should be be set to NO to properly deal with +# are not case sensitive the option should be set to NO to properly deal with # output files written for symbols that only differ in casing, such as for two # classes, one named CLASS and the other named Class, and to also support # references to files without having to specify the exact matching casing. On -# Windows (including Cygwin) and MacOS, users should typically set this option +# Windows (including Cygwin) and macOS, users should typically set this option # to NO, whereas on Linux or other Unix flavors it should typically be set to # YES. -# The default value is: system dependent. +# Possible values are: SYSTEM, NO and YES. +# The default value is: SYSTEM. CASE_SENSE_NAMES = NO -# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# If the HIDE_SCOPE_NAMES tag is set to NO then Doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then Doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO -# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class +# will show which file needs to be included to use the class. +# The default value is: YES. + +SHOW_HEADERFILE = YES + +# If the SHOW_INCLUDE_FILES tag is set to YES then Doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. @@ -563,7 +688,7 @@ SHOW_INCLUDE_FILES = YES SHOW_GROUPED_MEMB_INC = NO -# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. @@ -575,14 +700,14 @@ FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# If the SORT_MEMBER_DOCS tag is set to YES then Doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = NO -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# If the SORT_BRIEF_DOCS tag is set to YES then Doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. @@ -590,7 +715,7 @@ SORT_MEMBER_DOCS = NO SORT_BRIEF_DOCS = NO -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then Doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. @@ -602,7 +727,7 @@ SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# If the SORT_GROUP_NAMES tag is set to YES then Doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. @@ -619,11 +744,11 @@ SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# If the STRICT_PROTO_MATCHING option is enabled and Doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# simple string match. By disabling STRICT_PROTO_MATCHING Doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. @@ -693,24 +818,25 @@ SHOW_FILES = YES SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that -# doxygen should invoke to get the current version for each file (typically from +# Doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by doxygen. Whatever the program writes to standard output is used as the file +# by Doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by doxygen. The layout file controls the global structure of the generated +# by Doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. You can +# that represents Doxygen's defaults, run Doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. +# will be used as the name of the layout file. See also section "Changing the +# layout of pages" for information. # -# Note that if you run doxygen from a directory containing a file called -# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# Note that if you run Doxygen from a directory containing a file called +# DoxygenLayout.xml, Doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = @@ -725,19 +851,35 @@ LAYOUT_FILE = CITE_BIB_FILES = +# The EXTERNAL_TOOL_PATH tag can be used to extend the search path (PATH +# environment variable) so that external tools such as latex and gs can be +# found. +# Note: Directories specified with EXTERNAL_TOOL_PATH are added in front of the +# path already specified by the PATH variable, and are added in the order +# specified. +# Note: This option is particularly useful for macOS version 14 (Sonoma) and +# higher, when running Doxygen from Doxywizard, because in this case any user- +# defined changes to the PATH are ignored. A typical example on macOS is to set +# EXTERNAL_TOOL_PATH = /Library/TeX/texbin /usr/local/bin +# together with the standard path, the full search path used by doxygen when +# launching external tools will then become +# PATH=/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + +EXTERNAL_TOOL_PATH = + #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by doxygen. If QUIET is set to YES this implies that the +# standard output by Doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# generated to standard error (stderr) by Doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. @@ -745,52 +887,97 @@ QUIET = YES WARNINGS = YES -# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# If the WARN_IF_UNDOCUMENTED tag is set to YES then Doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES -# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some parameters -# in a documented function, or documenting parameters that don't exist or using -# markup commands wrongly. +# If the WARN_IF_DOC_ERROR tag is set to YES, Doxygen will generate warnings for +# potential errors in the documentation, such as documenting some parameters in +# a documented function twice, or documenting parameters that don't exist or +# using markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES +# If WARN_IF_INCOMPLETE_DOC is set to YES, Doxygen will warn about incomplete +# function parameter documentation. If set to NO, Doxygen will accept that some +# parameters have no documentation without warning. +# The default value is: YES. + +WARN_IF_INCOMPLETE_DOC = YES + # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return -# value. If set to NO, doxygen will only warn about wrong or incomplete -# parameter documentation, but not about the absence of documentation. If -# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# value. If set to NO, Doxygen will only warn about wrong parameter +# documentation, but not about the absence of documentation. If EXTRACT_ALL is +# set to YES then this flag will automatically be disabled. See also +# WARN_IF_INCOMPLETE_DOC # The default value is: NO. WARN_NO_PARAMDOC = YES -# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, Doxygen will warn about +# undocumented enumeration values. If set to NO, Doxygen will accept +# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: NO. + +WARN_IF_UNDOC_ENUM_VAL = NO + +# If WARN_LAYOUT_FILE option is set to YES, Doxygen will warn about issues found +# while parsing the user defined layout file, such as missing or wrong elements. +# See also LAYOUT_FILE for details. If set to NO, problems with the layout file +# will be suppressed. +# The default value is: YES. + +WARN_LAYOUT_FILE = YES + +# If the WARN_AS_ERROR tag is set to YES then Doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS -# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but -# at the end of the doxygen process doxygen will return with a non-zero status. -# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# then Doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the Doxygen process Doxygen will return with a non-zero status. +# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then Doxygen behaves +# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined Doxygen will not +# write the warning messages in between other messages but write them at the end +# of a run, in case a WARN_LOGFILE is defined the warning messages will be +# besides being in the defined file also be shown at the end of a run, unless +# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case +# the behavior will remain as with the setting FAIL_ON_WARNINGS. +# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. # The default value is: NO. WARN_AS_ERROR = NO -# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# The WARN_FORMAT tag determines the format of the warning messages that Doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) +# See also: WARN_LINE_FORMAT # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" +# In the $text part of the WARN_FORMAT command it is possible that a reference +# to a more specific place is given. To make it easier to jump to this place +# (outside of Doxygen) the user can define a custom "cut" / "paste" string. +# Example: +# WARN_LINE_FORMAT = "'vi $file +$line'" +# See also: WARN_FORMAT +# The default value is: at line $line of file $file. + +WARN_LINE_FORMAT = "at line $line of file $file" + # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard -# error (stderr). +# error (stderr). In case the file specified cannot be opened for writing the +# warning and error messages are written to standard error. When as file - is +# specified the warning and error messages are written to standard output +# (stdout). WARN_LOGFILE = @@ -807,31 +994,42 @@ WARN_LOGFILE = INPUT = # This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# that Doxygen parses. Internally Doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: # https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# See also: INPUT_FILE_ENCODING # The default value is: UTF-8. INPUT_ENCODING = UTF-8 +# This tag can be used to specify the character encoding of the source files +# that Doxygen parses. The INPUT_FILE_ENCODING tag can be used to specify +# character encoding on a per file pattern basis. Doxygen will compare the file +# name with each pattern and apply the encoding instead of the default +# INPUT_ENCODING if there is a match. The character encodings are a list of the +# form: pattern=encoding (like *.php=ISO-8859-1). +# See also: INPUT_ENCODING for further information on supported encodings. + +INPUT_FILE_ENCODING = + # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by doxygen. +# read by Doxygen. # # Note the list of default checked file patterns might differ from the list of # default file extension mappings. # -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, -# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, -# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, -# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), -# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, -# *.ucf, *.qsf and *.ice. +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, +# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, +# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, +# *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be +# provided as Doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.c \ *.cc \ @@ -854,7 +1052,7 @@ RECURSIVE = YES # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # -# Note that relative paths are relative to the directory from which doxygen is +# Note that relative paths are relative to the directory from which Doxygen is # run. EXCLUDE = EXCLUDE \ @@ -885,10 +1083,7 @@ EXCLUDE_PATTERNS = *.md # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, -# AClass::ANamespace, ANamespace::*Test -# -# Note that the wildcards are matched against the file with absolute path, so to -# exclude all test directories use the pattern */test/* +# ANamespace::AClass, ANamespace::*Test EXCLUDE_SYMBOLS = @@ -918,7 +1113,7 @@ EXAMPLE_RECURSIVE = NO IMAGE_PATH = -# The INPUT_FILTER tag can be used to specify a program that doxygen should +# The INPUT_FILTER tag can be used to specify a program that Doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # @@ -933,9 +1128,14 @@ IMAGE_PATH = # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # +# Note that Doxygen will use the data processed and written to standard output +# for further processing, therefore nothing else, like debug statements or used +# commands (so in case of a Windows batch file always use @echo OFF), should be +# written to standard output. +# # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. +# properly processed by Doxygen. INPUT_FILTER = @@ -948,7 +1148,7 @@ INPUT_FILTER = # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by doxygen. +# properly processed by Doxygen. FILTER_PATTERNS = @@ -970,10 +1170,28 @@ FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the doxygen output. +# and want to reuse the introduction page also for the Doxygen output. USE_MDFILE_AS_MAINPAGE = +# If the IMPLICIT_DIR_DOCS tag is set to YES, any README.md file found in sub- +# directories of the project's root, is used as the documentation for that sub- +# directory, except when the README.md starts with a \dir, \page or \mainpage +# command. If set to NO, the README.md file needs to start with an explicit \dir +# command in order to be used as directory documentation. +# The default value is: YES. + +IMPLICIT_DIR_DOCS = YES + +# The Fortran standard specifies that for fixed formatted Fortran code all +# characters from position 72 are to be considered as comment. A common +# extension is to allow longer lines before the automatic comment starts. The +# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can +# be processed before the automatic comment starts. +# Minimum value: 7, maximum value: 10000, default value: 72. + +FORTRAN_COMMENT_AFTER = 72 + #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- @@ -988,12 +1206,13 @@ USE_MDFILE_AS_MAINPAGE = SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, -# classes and enums directly into the documentation. +# multi-line macros, enums or list initialized variables directly into the +# documentation. # The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct Doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. @@ -1031,7 +1250,7 @@ REFERENCES_LINK_SOURCE = YES SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# point to the HTML generated by the htags(1) tool instead of Doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. @@ -1045,14 +1264,14 @@ SOURCE_TOOLTIPS = YES # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # -# The result: instead of the source browser generated by doxygen, the links to +# The result: instead of the source browser generated by Doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# If the VERBATIM_HEADERS tag is set the YES then Doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. @@ -1071,10 +1290,11 @@ VERBATIM_HEADERS = YES ALPHABETICAL_INDEX = YES -# In case all classes in a project start with a common prefix, all classes will -# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag -# can be used to specify a prefix (or a list of prefixes) that should be ignored -# while generating the index headers. +# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) +# that should be ignored while generating the index headers. The IGNORE_PREFIX +# tag works for classes, function and member names. The entity will be placed in +# the alphabetical list under the first letter of the entity name that remains +# after removing the prefix. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = @@ -1083,7 +1303,7 @@ IGNORE_PREFIX = # Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# If the GENERATE_HTML tag is set to YES, Doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES @@ -1104,40 +1324,40 @@ HTML_OUTPUT = html HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank doxygen will generate a +# each generated HTML page. If the tag is left blank Doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets -# that doxygen needs, which is dependent on the configuration options used (e.g. +# that Doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that doxygen normally +# for information on how to generate the default header that Doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of doxygen. For a description +# default header when upgrading to a newer version of Doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank doxygen will generate a standard +# generated HTML page. If the tag is left blank Doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer -# that doxygen normally uses. +# that Doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank doxygen will generate a default style sheet. +# the HTML output. If left blank Doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style -# sheet that doxygen normally uses. +# sheet that Doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. @@ -1147,13 +1367,18 @@ HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets -# created by doxygen. Using this option one can overrule certain style aspects. +# created by Doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the -# list). For an example see the documentation. +# list). +# Note: Since the styling of scrollbars can currently not be overruled in +# Webkit/Chromium, the styling will be left out of the default doxygen.css if +# one or more extra stylesheets have been specified. So if scrollbar +# customization is desired it has to be added explicitly. For an example see the +# documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = @@ -1168,9 +1393,22 @@ HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = +# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output +# should be rendered with a dark or light theme. +# Possible values are: LIGHT always generates light mode output, DARK always +# generates dark mode output, AUTO_LIGHT automatically sets the mode according +# to the user preference, uses light mode if no preference is set (the default), +# AUTO_DARK automatically sets the mode according to the user preference, uses +# dark mode if no preference is set and TOGGLE allows a user to switch between +# light and dark mode via a button. +# The default value is: AUTO_LIGHT. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE = AUTO_LIGHT + # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a colorwheel, see +# this color. Hue is specified as an angle on a color-wheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. @@ -1180,7 +1418,7 @@ HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use grayscales only. A +# in the HTML output. For a value of 0 the output will use gray-scales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1198,14 +1436,16 @@ HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 -# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting this -# to YES can help to show when doxygen was last run and thus if the -# documentation is up to date. -# The default value is: NO. +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_TIMESTAMP = NO +HTML_DYNAMIC_MENUS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the @@ -1215,6 +1455,33 @@ HTML_TIMESTAMP = NO HTML_DYNAMIC_SECTIONS = NO +# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be +# dynamically folded and expanded in the generated HTML source code. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_CODE_FOLDING = YES + +# If the HTML_COPY_CLIPBOARD tag is set to YES then Doxygen will show an icon in +# the top right corner of code and text fragments that allows the user to copy +# its content to the clipboard. Note this only works if supported by the browser +# and the web page is served via a secure context (see: +# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file: +# protocol. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COPY_CLIPBOARD = YES + +# Doxygen stores a couple of settings persistently in the browser (via e.g. +# cookies). By default these settings apply to all HTML pages generated by +# Doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store +# the settings under a project specific key, such that the user preferences will +# be stored separately. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_PROJECT_COOKIE = + # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to @@ -1232,7 +1499,7 @@ HTML_INDEX_NUM_ENTRIES = 100 # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To -# create a documentation set, doxygen will generate a Makefile in the HTML +# create a documentation set, Doxygen will generate a Makefile in the HTML # output directory. Running make will produce the docset in that directory and # running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at @@ -1251,6 +1518,13 @@ GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" +# This tag determines the URL of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDURL = + # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. @@ -1273,14 +1547,18 @@ DOCSET_PUBLISHER_ID = org.doxygen.Publisher DOCSET_PUBLISHER_NAME = Publisher -# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# If the GENERATE_HTMLHELP tag is set to YES then Doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# (see: -# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. +# on Windows. In the beginning of 2021 Microsoft took the original page, with +# a.o. the download links, offline (the HTML help workshop was already many +# years in maintenance mode). You can download the HTML help workshop from the +# web archives at Installation executable (see: +# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo +# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). # # The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# generated by Doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for @@ -1300,7 +1578,7 @@ CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, -# doxygen will try to run the HTML help compiler on the generated index.hhp. +# Doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1334,6 +1612,16 @@ BINARY_TOC = NO TOC_EXPAND = NO +# The SITEMAP_URL tag is used to specify the full URL of the place where the +# generated documentation will be placed on the server by the user during the +# deployment of the documentation. The generated sitemap is called sitemap.xml +# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL +# is specified no sitemap is generated. For information about the sitemap +# protocol see https://www.sitemaps.org +# This tag requires that the tag GENERATE_HTML is set to YES. + +SITEMAP_URL = + # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help @@ -1392,7 +1680,7 @@ QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location (absolute path -# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# including file name) of Qt's qhelpgenerator. If non-empty Doxygen will try to # run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1436,18 +1724,39 @@ DISABLE_INDEX = NO # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine-tune the look of the index. As an example, the default style -# sheet generated by doxygen has an example that shows how to put an image at -# the root of the tree instead of the PROJECT_NAME. Since the tree basically has -# the same information as the tab index, you could consider setting -# DISABLE_INDEX to YES when enabling this option. -# The default value is: NO. +# further fine tune the look of the index (see "Fine-tuning the output"). As an +# example, the default style sheet generated by Doxygen has an example that +# shows how to put an image at the root of the tree instead of the PROJECT_NAME. +# Since the tree basically has more details information than the tab index, you +# could consider setting DISABLE_INDEX to YES when enabling this option. +# The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO +# When GENERATE_TREEVIEW is set to YES, the PAGE_OUTLINE_PANEL option determines +# if an additional navigation panel is shown at the right hand side of the +# screen, displaying an outline of the contents of the main page, similar to +# e.g. https://developer.android.com/reference If GENERATE_TREEVIEW is set to +# NO, this option has no effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +PAGE_OUTLINE_PANEL = YES + +# When GENERATE_TREEVIEW is set to YES, the FULL_SIDEBAR option determines if +# the side bar is limited to only the treeview area (value NO) or if it should +# extend to the full height of the window (value YES). Setting this to YES gives +# a layout similar to e.g. https://docs.readthedocs.io with more room for +# contents, but less room for the project logo, title, and description. If +# GENERATE_TREEVIEW is set to NO, this option has no effect. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FULL_SIDEBAR = NO + # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# doxygen will group on one line in the generated HTML documentation. +# Doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. @@ -1456,6 +1765,12 @@ GENERATE_TREEVIEW = NO ENUM_VALUES_PER_LINE = 4 +# When the SHOW_ENUM_VALUES tag is set doxygen will show the specified +# enumeration values besides the enumeration mnemonics. +# The default value is: NO. + +SHOW_ENUM_VALUES = NO + # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. @@ -1463,32 +1778,45 @@ ENUM_VALUES_PER_LINE = 4 TREEVIEW_WIDTH = 250 -# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# If the EXT_LINKS_IN_WINDOW option is set to YES, Doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO +# If the OBFUSCATE_EMAILS tag is set to YES, Doxygen will obfuscate email +# addresses. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +OBFUSCATE_EMAILS = YES + +# If the HTML_FORMULA_FORMAT option is set to svg, Doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful -# doxygen run you need to manually remove any form_*.png images from the HTML +# Doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 -# Use the FORMULA_TRANSPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are not -# supported properly for IE 6.0, but are supported on all modern browsers. -# -# Note that when changing this option you need to delete any form_*.png files in -# the HTML output directory before the changes have effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. -FORMULA_TRANSPARENT = YES +FORMULA_MACROFILE = # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # https://www.mathjax.org) which uses client side JavaScript for the rendering @@ -1501,11 +1829,29 @@ FORMULA_TRANSPARENT = YES USE_MATHJAX = NO +# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. +# Note that the different versions of MathJax have different requirements with +# regards to the different settings, so it is possible that also other MathJax +# settings have to be changed when switching between the different MathJax +# versions. +# Possible values are: MathJax_2 and MathJax_3. +# The default value is: MathJax_2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_VERSION = MathJax_2 + # When MathJax is enabled you can set the default output format to be used for -# the MathJax output. See the MathJax site (see: -# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. +# the MathJax output. For more details about the output format see MathJax +# version 2 (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 +# (see: +# http://docs.mathjax.org/en/latest/web/components/output.html). # Possible values are: HTML-CSS (which is slower, but has the best -# compatibility), NativeMML (i.e. MathML) and SVG. +# compatibility. This is the name for Mathjax version 2, for MathJax version 3 +# this will be translated into chtml), NativeMML (i.e. MathML. Only supported +# for MathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This +# is the name for Mathjax version 3, for MathJax version 2 this will be +# translated into HTML-CSS) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1518,20 +1864,26 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from https://www.mathjax.org before deployment. -# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. +# MathJax from https://www.mathjax.org before deployment. The default value is: +# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 +# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example +# for MathJax version 2 (see +# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# For example for MathJax version 3 (see +# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): +# MATHJAX_EXTENSIONS = ams # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = -# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# The MATHJAX_CODEFILE tag can be used to specify a file with JavaScript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an @@ -1540,12 +1892,12 @@ MATHJAX_EXTENSIONS = MATHJAX_CODEFILE = -# When the SEARCHENGINE tag is enabled doxygen will generate a search box for -# the HTML output. The underlying search engine uses javascript and DHTML and +# When the SEARCHENGINE tag is enabled Doxygen will generate a search box for +# the HTML output. The underlying search engine uses JavaScript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. -# For large projects the javascript based search engine can be slow, then +# For large projects the JavaScript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically @@ -1564,7 +1916,7 @@ SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using JavaScript. There # are two flavors of web server based searching depending on the EXTERNAL_SEARCH -# setting. When disabled, doxygen will generate a PHP script for searching and +# setting. When disabled, Doxygen will generate a PHP script for searching and # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing # and searching needs to be provided by external tools. See the section # "External Indexing and Searching" for details. @@ -1573,7 +1925,7 @@ SEARCHENGINE = YES SERVER_BASED_SEARCH = NO -# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP +# When EXTERNAL_SEARCH tag is enabled Doxygen will no longer generate the PHP # script for searching. Instead the search results are written to an XML file # which needs to be processed by an external indexer. Doxygen will invoke an # external search engine pointed to by the SEARCHENGINE_URL option to obtain the @@ -1618,7 +1970,7 @@ SEARCHDATA_FILE = searchdata.xml EXTERNAL_SEARCH_ID = -# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through Doxygen # projects other than the one defined by this configuration file, but that are # all added to the same external search index. Each project needs to have a # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of @@ -1632,7 +1984,7 @@ EXTRA_SEARCH_MAPPINGS = # Configuration options related to the LaTeX output #--------------------------------------------------------------------------- -# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. +# If the GENERATE_LATEX tag is set to YES, Doxygen will generate LaTeX output. # The default value is: YES. GENERATE_LATEX = NO @@ -1667,7 +2019,17 @@ LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex -# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX +# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to +# generate index for LaTeX. In case there is no backslash (\) as first character +# it will be automatically added in the LaTeX code. +# Note: This tag is used in the generated output file (.tex). +# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. +# The default value is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_MAKEINDEX_CMD = makeindex + +# If the COMPACT_LATEX tag is set to YES, Doxygen generates more compact LaTeX # documents. This may be useful for small projects and may help to save some # trees in general. # The default value is: NO. @@ -1696,36 +2058,38 @@ PAPER_TYPE = a4 EXTRA_PACKAGES = -# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the -# generated LaTeX document. The header should contain everything until the first -# chapter. If it is left blank doxygen will generate a standard header. See -# section "Doxygen usage" for information on how to let doxygen write the -# default header to a separate file. +# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for +# the generated LaTeX document. The header should contain everything until the +# first chapter. If it is left blank Doxygen will generate a standard header. It +# is highly recommended to start with a default header using +# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty +# and then modify the file new_header.tex. See also section "Doxygen usage" for +# information on how to generate the default header that Doxygen normally uses. # -# Note: Only use a user-defined header if you know what you are doing! The -# following commands have a special meaning inside the header: $title, -# $datetime, $date, $doxygenversion, $projectname, $projectnumber, -# $projectbrief, $projectlogo. Doxygen will replace $title with the empty -# string, for the replacement values of the other commands the user is referred -# to HTML_HEADER. +# Note: Only use a user-defined header if you know what you are doing! +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of Doxygen. The following +# commands have a special meaning inside the header (and footer): For a +# description of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HEADER = -# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the -# generated LaTeX document. The footer should contain everything after the last -# chapter. If it is left blank doxygen will generate a standard footer. See +# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for +# the generated LaTeX document. The footer should contain everything after the +# last chapter. If it is left blank Doxygen will generate a standard footer. See # LATEX_HEADER for more information on how to generate a default footer and what -# special commands can be used inside the footer. -# -# Note: Only use a user-defined footer if you know what you are doing! +# special commands can be used inside the footer. See also section "Doxygen +# usage" for information on how to generate the default footer that Doxygen +# normally uses. Note: Only use a user-defined footer if you know what you are +# doing! # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_FOOTER = # The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined # LaTeX style sheets that are included after the standard style sheets created -# by doxygen. Using this option one can overrule certain style aspects. Doxygen +# by Doxygen. Using this option one can overrule certain style aspects. Doxygen # will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the @@ -1751,7 +2115,7 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES -# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as +# If the USE_PDFLATEX tag is set to YES, Doxygen will use the engine as # specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX # files. Set this option to YES, to get a higher quality PDF documentation. # @@ -1761,53 +2125,49 @@ PDF_HYPERLINKS = YES USE_PDFLATEX = YES -# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode -# command to the generated LaTeX files. This will instruct LaTeX to keep running -# if errors occur, instead of asking the user for help. This option is also used -# when generating formulas in HTML. +# The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error. +# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch +# mode nothing is printed on the terminal, errors are scrolled as if is +# hit at every error; missing files that TeX tries to input or request from +# keyboard input (\read on a not open input stream) cause the job to abort, +# NON_STOP In nonstop mode the diagnostic message will appear on the terminal, +# but there is no possibility of user interaction just like in batch mode, +# SCROLL In scroll mode, TeX will stop only for missing files to input or if +# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at +# each error, asking for user intervention. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_BATCHMODE = NO -# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the +# If the LATEX_HIDE_INDICES tag is set to YES then Doxygen will not include the # index chapters (such as File Index, Compound Index, etc.) in the output. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HIDE_INDICES = NO -# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source -# code with syntax highlighting in the LaTeX output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_SOURCE_CODE = NO - # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See # https://en.wikipedia.org/wiki/BibTeX and \cite for more info. -# The default value is: plain. +# The default value is: plainnat. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_BIB_STYLE = plain -# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated -# page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: NO. +# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) +# path from which the emoji images will be read. If a relative path is entered, +# it will be relative to the LATEX_OUTPUT directory. If left blank the +# LATEX_OUTPUT directory will be used. # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_TIMESTAMP = NO +LATEX_EMOJI_DIRECTORY = #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- -# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The +# If the GENERATE_RTF tag is set to YES, Doxygen will generate RTF output. The # RTF output is optimized for Word 97 and may not look too pretty with other RTF # readers/editors. # The default value is: NO. @@ -1822,7 +2182,7 @@ GENERATE_RTF = NO RTF_OUTPUT = rtf -# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF +# If the COMPACT_RTF tag is set to YES, Doxygen generates more compact RTF # documents. This may be useful for small projects and may help to save some # trees in general. # The default value is: NO. @@ -1842,38 +2202,36 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to doxygen's +# Load stylesheet definitions from file. Syntax is similar to Doxygen's # configuration file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. # # See also section "Doxygen usage" for information on how to generate the -# default style sheet that doxygen normally uses. +# default style sheet that Doxygen normally uses. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an RTF document. Syntax is -# similar to doxygen's configuration file. A template extensions file can be +# similar to Doxygen's configuration file. A template extensions file can be # generated using doxygen -e rtf extensionFile. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_EXTENSIONS_FILE = -# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code -# with syntax highlighting in the RTF output. -# -# Note that which sources are shown also depends on other settings such as -# SOURCE_BROWSER. -# The default value is: NO. +# The RTF_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the RTF_OUTPUT output directory. +# Note that the files will be copied as-is; there are no commands or markers +# available. # This tag requires that the tag GENERATE_RTF is set to YES. -RTF_SOURCE_CODE = NO +RTF_EXTRA_FILES = #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- -# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for +# If the GENERATE_MAN tag is set to YES, Doxygen will generate man pages for # classes and files. # The default value is: NO. @@ -1904,7 +2262,7 @@ MAN_EXTENSION = .3 MAN_SUBDIR = -# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, then it # will generate one additional man file for each entity documented in the real # man page(s). These additional files only source the real man page, but without # them the man command would be unable to find the correct page. @@ -1917,7 +2275,7 @@ MAN_LINKS = NO # Configuration options related to the XML output #--------------------------------------------------------------------------- -# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that +# If the GENERATE_XML tag is set to YES, Doxygen will generate an XML file that # captures the structure of the code including all documentation. # The default value is: NO. @@ -1931,7 +2289,7 @@ GENERATE_XML = NO XML_OUTPUT = xml -# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program +# If the XML_PROGRAMLISTING tag is set to YES, Doxygen will dump the program # listings (including syntax highlighting and cross-referencing information) to # the XML output. Note that enabling this will significantly increase the size # of the XML output. @@ -1940,11 +2298,18 @@ XML_OUTPUT = xml XML_PROGRAMLISTING = YES +# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, Doxygen will include +# namespace members in file scope as well, matching the HTML output. +# The default value is: NO. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_NS_MEMB_FILE_SCOPE = NO + #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- -# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files +# If the GENERATE_DOCBOOK tag is set to YES, Doxygen will generate Docbook files # that can be used to generate PDF. # The default value is: NO. @@ -1958,32 +2323,49 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook -# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the -# program listings (including syntax highlighting and cross-referencing -# information) to the DOCBOOK output. Note that enabling this will significantly -# increase the size of the DOCBOOK output. -# The default value is: NO. -# This tag requires that the tag GENERATE_DOCBOOK is set to YES. - -DOCBOOK_PROGRAMLISTING = NO - #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- -# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an -# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures +# If the GENERATE_AUTOGEN_DEF tag is set to YES, Doxygen will generate an +# AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures # the structure of the code including all documentation. Note that this feature # is still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to Sqlite3 output +#--------------------------------------------------------------------------- + +# If the GENERATE_SQLITE3 tag is set to YES Doxygen will generate a Sqlite3 +# database with symbols found by Doxygen stored in tables. +# The default value is: NO. + +GENERATE_SQLITE3 = NO + +# The SQLITE3_OUTPUT tag is used to specify where the Sqlite3 database will be +# put. If a relative path is entered the value of OUTPUT_DIRECTORY will be put +# in front of it. +# The default directory is: sqlite3. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_OUTPUT = sqlite3 + +# The SQLITE3_RECREATE_DB tag is set to YES, the existing doxygen_sqlite3.db +# database file will be recreated with each Doxygen run. If set to NO, Doxygen +# will warn if a database file is already found and not modify it. +# The default value is: YES. +# This tag requires that the tag GENERATE_SQLITE3 is set to YES. + +SQLITE3_RECREATE_DB = YES + #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- -# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module +# If the GENERATE_PERLMOD tag is set to YES, Doxygen will generate a Perl module # file that captures the structure of the code including all documentation. # # Note that this feature is still experimental and incomplete at the moment. @@ -1991,7 +2373,7 @@ GENERATE_AUTOGEN_DEF = NO GENERATE_PERLMOD = NO -# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary +# If the PERLMOD_LATEX tag is set to YES, Doxygen will generate the necessary # Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI # output from the Perl module output. # The default value is: NO. @@ -2021,13 +2403,13 @@ PERLMOD_MAKEVAR_PREFIX = # Configuration options related to the preprocessor #--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all +# If the ENABLE_PREPROCESSING tag is set to YES, Doxygen will evaluate all # C-preprocessor directives found in the sources and include files. # The default value is: YES. ENABLE_PREPROCESSING = YES -# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names +# If the MACRO_EXPANSION tag is set to YES, Doxygen will expand all macro names # in the source code. If set to NO, only conditional compilation will be # performed. Macro expansion can be done in a controlled way by setting # EXPAND_ONLY_PREDEF to YES. @@ -2053,7 +2435,8 @@ SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by the -# preprocessor. +# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of +# RECURSIVE has no effect here. # This tag requires that the tag SEARCH_INCLUDES is set to YES. INCLUDE_PATH = @@ -2074,7 +2457,9 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = __cdecl=, ARDUINO_ARCH_ESP32=1, ARDUINO_FUNHOUSE_ESP32S2=1 +PREDEFINED = "__cdecl=," \ + "ARDUINO_ARCH_ESP32=1," \ + ARDUINO_FUNHOUSE_ESP32S2=1 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -2085,7 +2470,7 @@ PREDEFINED = __cdecl=, ARDUINO_ARCH_ESP32=1, ARDUINO_FUNHOUSE_ESP32S EXPAND_AS_DEFINED = -# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will +# If the SKIP_FUNCTION_MACROS tag is set to YES then Doxygen's preprocessor will # remove all references to function-like macros that are alone on a line, have # an all uppercase name, and do not end with a semicolon. Such function macros # are typically used for boiler-plate code, and will confuse the parser if not @@ -2109,26 +2494,26 @@ SKIP_FUNCTION_MACROS = YES # section "Linking to external documentation" for more information about the use # of tag files. # Note: Each tag file must have a unique name (where the name does NOT include -# the path). If a tag file is not located in the directory in which doxygen is +# the path). If a tag file is not located in the directory in which Doxygen is # run, you must also specify the path to the tagfile here. TAGFILES = -# When a file name is specified after GENERATE_TAGFILE, doxygen will create a +# When a file name is specified after GENERATE_TAGFILE, Doxygen will create a # tag file that is based on the input files it reads. See section "Linking to # external documentation" for more information about the usage of tag files. GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES, all external class will be listed in -# the class index. If set to NO, only the inherited external classes will be -# listed. +# If the ALLEXTERNALS tag is set to YES, all external classes and namespaces +# will be listed in the class and namespace index. If set to NO, only the +# inherited external classes will be listed. # The default value is: NO. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed -# in the modules index. If set to NO, only the current project's groups will be +# in the topic index. If set to NO, only the current project's groups will be # listed. # The default value is: YES. @@ -2142,42 +2527,26 @@ EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES #--------------------------------------------------------------------------- -# Configuration options related to the dot tool +# Configuration options related to diagram generator tools #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram -# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to -# NO turns the diagrams off. Note that this option also works with HAVE_DOT -# disabled, but it is recommended to install and use dot, since it yields more -# powerful graphs. -# The default value is: YES. - -CLASS_DIAGRAMS = YES - -# You can include diagrams made with dia in doxygen documentation. Doxygen will -# then run dia to produce the diagram and insert it in the documentation. The -# DIA_PATH tag allows you to specify the directory where the dia binary resides. -# If left empty dia is assumed to be found in the default search path. - -DIA_PATH = - # If set to YES the inheritance and collaboration graphs will hide inheritance # and usage relations if the target is undocumented or is not a class. # The default value is: YES. HIDE_UNDOC_RELATIONS = YES -# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# If you set the HAVE_DOT tag to YES then Doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz (see: -# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # Bell Labs. The other options in this section have no effect if this option is # set to NO # The default value is: NO. HAVE_DOT = NO -# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed -# to run in parallel. When set to 0 doxygen will base this on the number of +# The DOT_NUM_THREADS specifies the number of dot invocations Doxygen is allowed +# to run in parallel. When set to 0 Doxygen will base this on the number of # processors available in the system. You can set it explicitly to a value # larger than 0 to get control over the balance between CPU load and processing # speed. @@ -2186,55 +2555,83 @@ HAVE_DOT = NO DOT_NUM_THREADS = 0 -# When you want a differently looking font in the dot files that doxygen -# generates you can specify the font name using DOT_FONTNAME. You need to make -# sure dot is able to find the font, which can be done by putting it in a -# standard location or by setting the DOTFONTPATH environment variable or by -# setting DOT_FONTPATH to the directory containing the font. -# The default value is: Helvetica. +# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of +# subgraphs. When you want a differently looking font in the dot files that +# Doxygen generates you can specify fontname, fontcolor and fontsize attributes. +# For details please see Node, +# Edge and Graph Attributes specification You need to make sure dot is able +# to find the font, which can be done by putting it in a standard location or by +# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the +# directory containing the font. Default graphviz fontsize is 14. +# The default value is: fontname=Helvetica,fontsize=10. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTNAME = Helvetica +DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10" -# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of -# dot graphs. -# Minimum value: 4, maximum value: 24, default value: 10. +# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can +# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. Complete documentation about +# arrows shapes. +# The default value is: labelfontname=Helvetica,labelfontsize=10. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTSIZE = 10 +DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10" -# By default doxygen will tell dot to use the default font as specified with -# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set -# the path where dot can find it using this tag. +# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes +# around nodes set 'shape=plain' or 'shape=plaintext' Shapes specification +# The default value is: shape=box,height=0.2,width=0.4. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" + +# You can set the path where dot can find font specified with fontname in +# DOT_COMMON_ATTR and others dot attributes. # This tag requires that the tag HAVE_DOT is set to YES. DOT_FONTPATH = -# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for -# each documented class showing the direct and indirect inheritance relations. -# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then Doxygen will +# generate a graph for each documented class showing the direct and indirect +# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and +# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case +# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the +# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used. +# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance +# relations will be shown as texts / links. Explicit enabling an inheritance +# graph or choosing a different representation for an inheritance graph of a +# specific class, can be accomplished by means of the command \inheritancegraph. +# Disabling an inheritance graph can be accomplished by means of the command +# \hideinheritancegraph. +# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN. # The default value is: YES. -# This tag requires that the tag HAVE_DOT is set to YES. CLASS_GRAPH = YES -# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a +# If the COLLABORATION_GRAPH tag is set to YES then Doxygen will generate a # graph for each documented class showing the direct and indirect implementation # dependencies (inheritance, containment, and class references variables) of the -# class with other documented classes. +# class with other documented classes. Explicit enabling a collaboration graph, +# when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the +# command \collaborationgraph. Disabling a collaboration graph can be +# accomplished by means of the command \hidecollaborationgraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. COLLABORATION_GRAPH = YES -# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for -# groups, showing the direct groups dependencies. +# If the GROUP_GRAPHS tag is set to YES then Doxygen will generate a graph for +# groups, showing the direct groups dependencies. Explicit enabling a group +# dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means +# of the command \groupgraph. Disabling a directory graph can be accomplished by +# means of the command \hidegroupgraph. See also the chapter Grouping in the +# manual. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GROUP_GRAPHS = YES -# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and +# If the UML_LOOK tag is set to YES, Doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. # The default value is: NO. @@ -2255,6 +2652,37 @@ UML_LOOK = NO UML_LIMIT_NUM_FIELDS = 10 +# If the UML_LOOK tag is enabled, field labels are shown along the edge between +# two class nodes. If there are many fields and many nodes the graph may become +# too cluttered. The UML_MAX_EDGE_LABELS threshold limits the number of items to +# make the size more manageable. Set this to 0 for no limit. +# Minimum value: 0, maximum value: 100, default value: 10. +# This tag requires that the tag UML_LOOK is set to YES. + +UML_MAX_EDGE_LABELS = 10 + +# If the DOT_UML_DETAILS tag is set to NO, Doxygen will show attributes and +# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS +# tag is set to YES, Doxygen will add type and arguments for attributes and +# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, Doxygen +# will not generate fields with class member information in the UML graphs. The +# class diagrams will look similar to the default class diagrams but using UML +# notation for the relationships. +# Possible values are: NO, YES and NONE. +# The default value is: NO. +# This tag requires that the tag UML_LOOK is set to YES. + +DOT_UML_DETAILS = NO + +# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters +# to display on a single line. If the actual line length exceeds this threshold +# significantly it will be wrapped across multiple lines. Some heuristics are +# applied to avoid ugly line breaks. +# Minimum value: 0, maximum value: 1000, default value: 17. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_WRAP_THRESHOLD = 17 + # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and # collaboration graphs will show the relations between templates and their # instances. @@ -2264,24 +2692,29 @@ UML_LIMIT_NUM_FIELDS = 10 TEMPLATE_RELATIONS = NO # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to -# YES then doxygen will generate a graph for each documented file showing the +# YES then Doxygen will generate a graph for each documented file showing the # direct and indirect include dependencies of the file with other documented -# files. +# files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO, +# can be accomplished by means of the command \includegraph. Disabling an +# include graph can be accomplished by means of the command \hideincludegraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. INCLUDE_GRAPH = YES # If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are -# set to YES then doxygen will generate a graph for each documented file showing +# set to YES then Doxygen will generate a graph for each documented file showing # the direct and indirect include dependencies of the file with other documented -# files. +# files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set +# to NO, can be accomplished by means of the command \includedbygraph. Disabling +# an included by graph can be accomplished by means of the command +# \hideincludedbygraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. INCLUDED_BY_GRAPH = YES -# If the CALL_GRAPH tag is set to YES then doxygen will generate a call +# If the CALL_GRAPH tag is set to YES then Doxygen will generate a call # dependency graph for every global function or class method. # # Note that enabling this option will significantly increase the time of a run. @@ -2293,7 +2726,7 @@ INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO -# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller +# If the CALLER_GRAPH tag is set to YES then Doxygen will generate a caller # dependency graph for every global function or class method. # # Note that enabling this option will significantly increase the time of a run. @@ -2305,44 +2738,59 @@ CALL_GRAPH = NO CALLER_GRAPH = NO -# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical +# If the GRAPHICAL_HIERARCHY tag is set to YES then Doxygen will graphical # hierarchy of all classes instead of a textual one. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GRAPHICAL_HIERARCHY = YES -# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the +# If the DIRECTORY_GRAPH tag is set to YES then Doxygen will show the # dependencies a directory has on other directories in a graphical way. The # dependency relations are determined by the #include relations between the -# files in the directories. +# files in the directories. Explicit enabling a directory graph, when +# DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command +# \directorygraph. Disabling a directory graph can be accomplished by means of +# the command \hidedirectorygraph. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. DIRECTORY_GRAPH = YES +# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels +# of child directories generated in directory dependency graphs by dot. +# Minimum value: 1, maximum value: 25, default value: 1. +# This tag requires that the tag DIRECTORY_GRAPH is set to YES. + +DIR_GRAPH_MAX_DEPTH = 1 + # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. For an explanation of the image formats see the section # output formats in the documentation of the dot tool (Graphviz (see: -# http://www.graphviz.org/)). -# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order -# to make the SVG files visible in IE 9+ (other browsers do not have this -# requirement). +# https://www.graphviz.org/)). +# +# Note the formats svg:cairo and svg:cairo:cairo cannot be used in combination +# with INTERACTIVE_SVG (the INTERACTIVE_SVG will be set to NO). # Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo, -# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and -# png:gdiplus:gdiplus. +# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus, +# png:gdiplus:gdiplus, svg:cairo, svg:cairo:cairo, svg:svg, svg:svg:core, +# gif:cairo, gif:cairo:gd, gif:cairo:gdiplus, gif:gdiplus, gif:gdiplus:gdiplus, +# gif:gd, gif:gd:gd, jpg:cairo, jpg:cairo:gd, jpg:cairo:gdiplus, jpg:gd, +# jpg:gd:gd, jpg:gdiplus and jpg:gdiplus:gdiplus. # The default value is: png. # This tag requires that the tag HAVE_DOT is set to YES. DOT_IMAGE_FORMAT = png -# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to -# enable generation of interactive SVG images that allow zooming and panning. +# If DOT_IMAGE_FORMAT is set to svg or svg:svg or svg:svg:core, then this option +# can be set to YES to enable generation of interactive SVG images that allow +# zooming and panning. # # Note that this requires a modern browser other than Internet Explorer. Tested # and working are Firefox, Chrome, Safari, and Opera. -# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make -# the SVG files visible. Older versions of IE do not have SVG support. +# +# Note This option will be automatically disabled when DOT_IMAGE_FORMAT is set +# to svg:cairo or svg:cairo:cairo. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2361,11 +2809,12 @@ DOT_PATH = DOTFILE_DIRS = -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the \mscfile -# command). +# You can include diagrams made with dia in Doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. -MSCFILE_DIRS = +DIA_PATH = # The DIAFILE_DIRS tag can be used to specify one or more directories that # contain dia files that are included in the documentation (see the \diafile @@ -2373,28 +2822,34 @@ MSCFILE_DIRS = DIAFILE_DIRS = -# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the -# path where java can find the plantuml.jar file. If left blank, it is assumed -# PlantUML is not used or called during a preprocessing step. Doxygen will -# generate a warning when it encounters a \startuml command in this case and -# will not generate output for the diagram. +# When using PlantUML, the PLANTUML_JAR_PATH tag should be used to specify the +# path where java can find the plantuml.jar file or to the filename of jar file +# to be used. If left blank, it is assumed PlantUML is not used or called during +# a preprocessing step. Doxygen will generate a warning when it encounters a +# \startuml command in this case and will not generate output for the diagram. PLANTUML_JAR_PATH = -# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a -# configuration file for plantuml. +# When using PlantUML, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for PlantUML. PLANTUML_CFG_FILE = -# When using plantuml, the specified paths are searched for files specified by -# the !include statement in a plantuml block. +# When using PlantUML, the specified paths are searched for files specified by +# the !include statement in a PlantUML block. PLANTUML_INCLUDE_PATH = +# The PLANTUMLFILE_DIRS tag can be used to specify one or more directories that +# contain PlantUml files that are included in the documentation (see the +# \plantumlfile command). + +PLANTUMLFILE_DIRS = + # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes # that will be shown in the graph. If the number of nodes in a graph becomes -# larger than this value, doxygen will truncate the graph, which is visualized -# by representing a node as a red box. Note that doxygen if the number of direct +# larger than this value, Doxygen will truncate the graph, which is visualized +# by representing a node as a red box. Note that if the number of direct # children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that # the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. @@ -2415,18 +2870,6 @@ DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 -# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent -# background. This is disabled by default, because dot on Windows does not seem -# to support this out of the box. -# -# Warning: Depending on the platform used, enabling this option may lead to -# badly anti-aliased labels on the edges of a graph (i.e. they become hard to -# read). -# The default value is: NO. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_TRANSPARENT = NO - # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) support @@ -2436,19 +2879,37 @@ DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO -# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page +# If the GENERATE_LEGEND tag is set to YES Doxygen will generate a legend page # explaining the meaning of the various boxes and arrows in the dot generated # graphs. +# Note: This tag requires that UML_LOOK isn't set, i.e. the Doxygen internal +# graphical representation for inheritance and collaboration diagrams is used. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate +# If the DOT_CLEANUP tag is set to YES, Doxygen will remove the intermediate # files that are used to generate the various graphs. # -# Note: This setting is not only used for dot files but also for msc and -# plantuml temporary files. +# Note: This setting is not only used for dot files but also for msc temporary +# files. # The default value is: YES. DOT_CLEANUP = YES + +# You can define message sequence charts within Doxygen comments using the \msc +# command. If the MSCGEN_TOOL tag is left empty (the default), then Doxygen will +# use a built-in version of mscgen tool to produce the charts. Alternatively, +# the MSCGEN_TOOL tag can also specify the name an external tool. For instance, +# specifying prog as the value, Doxygen will call the tool as prog -T +# -o . The external tool should support +# output file formats "png", "eps", "svg", and "ismap". + +MSCGEN_TOOL = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 17b19a3c1..57d839b51 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -1684,10 +1684,30 @@ bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field, } // Attempt to add or replace a display component - bool did_add = - WS._displayController->Handle_Display_AddOrReplace(&msgAddReq); - // TODO: Add response handling and publishing here, for now it always - // returns true and doesnt publish back to the broker + bool did_add = WS._displayController->Handle_Display_AddOrReplace(&msgAddReq); + + // Create a DisplayResponse message + wippersnapper_signal_v1_DisplayResponse msgResp = wippersnapper_signal_v1_DisplayResponse_init_zero; + msgResp.which_payload = wippersnapper_signal_v1_DisplayResponse_display_added_tag; + msgResp.payload.display_added.did_add = did_add; + strncpy(msgResp.payload.display_added.name, msgAddReq.name, sizeof(msgResp.payload.display_added.name)); + + // Encode and publish response back to broker + memset(WS._buffer_outgoing, 0, sizeof(WS._buffer_outgoing)); + pb_ostream_t ostream = pb_ostream_from_buffer(WS._buffer_outgoing, sizeof(WS._buffer_outgoing)); + if (!ws_pb_encode(&ostream, wippersnapper_signal_v1_DisplayResponse_fields, &msgResp)) { + WS_DEBUG_PRINTLN("ERROR: Unable to encode display response message!"); + return false; + } + + size_t msgSz; + pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_DisplayResponse_fields, &msgResp); + WS_DEBUG_PRINT("Publishing DisplayResponse Message..."); + if (!WS._mqtt->publish(WS._topic_signal_display_device, WS._buffer_outgoing, msgSz, 1)) { + WS_DEBUG_PRINTLN("ERROR: Failed to DisplayResponse Response!"); + } else { + WS_DEBUG_PRINTLN("Published!"); + } } else if (field->tag == wippersnapper_signal_v1_DisplayRequest_display_write_tag) { // Decode message into a DisplayAddRequest @@ -1698,7 +1718,23 @@ bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field, WS_DEBUG_PRINTLN("ERROR: Failure decoding DisplayWrite message!"); return false; } + // Attempt to write to a display WS._displayController->Handle_Display_Write(&msgWrite); + } else if (field->tag == wippersnapper_signal_v1_DisplayRequest_display_remove_tag) { + // Decode message into a DisplayRemoveRequest + wippersnapper_display_v1_DisplayRemove msgRemove = + wippersnapper_display_v1_DisplayRemove_init_zero; + if (!ws_pb_decode(stream, + wippersnapper_display_v1_DisplayRemove_fields, + &msgRemove)) { + WS_DEBUG_PRINTLN("ERROR: Failure decoding DisplayRemove message!"); + return false; + } + // Attempt to remove a display + WS._displayController->Handle_Display_Remove(&msgRemove); + } else { + WS_DEBUG_PRINTLN("ERROR: Display message type not found!"); + return false; } return true; } diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index a80adf0ed..ebdef51c4 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -25,7 +25,11 @@ DisplayController::DisplayController() { @brief Destructor */ DisplayController::~DisplayController() { - // TODO + // Clean up all display hardware instances + for (DisplayHardware *hw_instance : _hw_instances) { + delete hw_instance; + } + _hw_instances.clear(); } /*! diff --git a/src/components/display/controller.h b/src/components/display/controller.h index f4c087e30..6dd3e4c05 100644 --- a/src/components/display/controller.h +++ b/src/components/display/controller.h @@ -35,7 +35,6 @@ class DisplayController { wippersnapper_display_v1_DisplayAddOrReplace *msgAdd); bool Handle_Display_Remove(wippersnapper_display_v1_DisplayRemove *msgRemove); bool Handle_Display_Write(wippersnapper_display_v1_DisplayWrite *msgWrite); - private: std::vector _hw_instances; ///< Holds pointers to DisplayHardware instances diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index c7d624836..9d50429da 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -15,8 +15,8 @@ #ifndef WS_DISP_DRV_BASE_H #define WS_DISP_DRV_BASE_H -#include "Adafruit_ThinkInk.h" #include "Wippersnapper.h" +#include "Adafruit_ThinkInk.h" /*! @brief Abstract base class for display drivers. diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h new file mode 100644 index 000000000..0320cf1eb --- /dev/null +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h @@ -0,0 +1,139 @@ +/*! + * @file src/components/display/drivers/ThinkInk_290_Grayscale4_T5.h + * + * Driver for ThinkInk 2.9" Grayscale 4-level T5 display (present on the + * pre-2025 version of the Adafruit MagTag) + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DRV_THINKINK_GRAYSCALE4_T5_H +#define WS_DRV_THINKINK_GRAYSCALE4_T5_H + +#include "dispDrvBase.h" + +/*! + @brief Driver for a ThinkInk 2.9" Grayscale 4-level T5 display (pre-2025 version of the Adafruit MagTag). +*/ +class dispDrvThinkInkGrayscale4T5 : public dispDrvBase { +public: + /*! + @brief Constructor for the ThinkInk Grayscale 4-level EAAMFGN display + driver. + @param dc + Data/Command pin for the display. + @param rst + Reset pin for the display. + @param cs + Chip Select pin for the display. + @param sram_cs + Optional SRAM Chip Select pin for E-Ink displays that support it. + @param busy + Optional Busy pin for the display. + */ + dispDrvThinkInkGrayscale4T5(int16_t dc, int16_t rst, int16_t cs, + int16_t sram_cs = -1, int16_t busy = -1) + : dispDrvBase(dc, rst, cs, sram_cs, busy), _display(nullptr) {} + + ~dispDrvThinkInkGrayscale4T5() { + if (_display) { + delete _display; + _display = nullptr; + } + } + + /*! + @brief Attempts to initialize the ThinkInk Grayscale 4-level EAAMFGN + display driver. + @param mode + The ThinkInk mode to use for the display. + @param reset + Whether to reset the display before initialization. + @return True if the display was initialized successfully, false otherwise. + */ + bool begin(thinkinkmode_t mode, bool reset = true) override { + _display = new ThinkInk_290_Grayscale4_T5(_pin_dc, _pin_rst, _pin_cs, + _pin_sram_cs, _pin_busy); + if (!_display) + return false; // Allocation failed + + // Initialize the display + _display->begin(mode); + // Configure display settings + _text_sz = 3; + _display->setTextSize(_text_sz); + _display->setTextColor(EPD_BLACK); + _display->setTextWrap(false); + _height = _display->height(); + _width = _display->width(); + // Clear the display buffer + _display->clearBuffer(); + _display->display(); + + return true; + } + + /*! + @brief Writes a message to the display. + @param message + The message to write to the display. + @note This method overrides the base class method to provide specific + functionality for the Think Ink Grayscale 4 EAAMGFGN driver. + */ + virtual void writeMessage(const char *message) override { + if (_display == nullptr) + return; + + // Start with a fresh display buffer + _display->clearBuffer(); + int16_t y_idx = 0; + _display->setCursor(0, y_idx); + + // Calculate the line height based on the text size (NOTE: base height is + // 8px) + int16_t line_height = 8 * _text_sz; + uint16_t c_idx = 0; + size_t msg_size = strlen(message); + for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) { + if (y_idx + line_height > _height) + break; + if (message[i] == '\\' && i + 1 < msg_size && + (message[i + 1] == 'n' || message[i + 1] == 'r')) { + // Handle \r\n sequence as a single newline + if (message[i + 1] == 'r' && i + 3 < msg_size && + message[i + 2] == '\\' && message[i + 3] == 'n') { + // Skip to the next line + if (y_idx + line_height > _height) + break; + y_idx += line_height; + _display->setCursor(0, y_idx); + i += 3; + } else if (message[i + 1] == 'n') { + // Skip to the next line + if (y_idx + line_height > _height) + break; + y_idx += line_height; + _display->setCursor(0, y_idx); + i++; + } + } else if (message[i] == 0xC2 && message[i + 1] == 0xB0) { + _display->write(char(248)); + i++; + } else { + _display->print(message[i]); + } + } + _display->display(); + } + +private: + ThinkInk_290_Grayscale4_T5 *_display; +}; + +#endif // WS_DRV_THINKINK_GRAYSCALE4_T5_H \ No newline at end of file diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 7a67a3dc0..eb34f8b8a 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -23,17 +23,30 @@ using FnCreateDispDrv = // Factory for creating a new display drivers // NOTE: When you add a new display driver, make sure to add it to the factory! static const std::map FactoryDrvDisp = { - {"grayscale4_eaamfgn", + {"thinkink-gs4-eaamfgn", [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, int16_t busy) -> dispDrvBase * { return new drvDispThinkInkGrayscale4Eaamfgn(dc, rst, cs, sram_cs, busy); }}, - {"magtag_2025", + {"thinkink-magtag-2025", [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, int16_t busy) -> dispDrvBase * { return new drvDispThinkInkGrayscale4Eaamfgn(dc, rst, cs, sram_cs, busy); - }}}; + }}, + {"thinkink-gs4-t5", + [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, + int16_t busy) -> dispDrvBase * { + return new dispDrvThinkInkGrayscale4T5(dc, rst, cs, sram_cs, busy); + }}, + {"thinkink-magtag-pre-2025", + [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, + int16_t busy) -> dispDrvBase * { + return new dispDrvThinkInkGrayscale4T5(dc, rst, cs, sram_cs, busy); + }} + }; + + /*! @brief Creates a new display driver instance based on the driver name. @param driver_name diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 570b2e1b8..00cba9625 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -15,10 +15,11 @@ #ifndef WS_DISPLAY_HARDWARE_H #define WS_DISPLAY_HARDWARE_H #include "Wippersnapper.h" -#include "drivers/dispDrvBase.h" -#include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h" #include #include +#include "drivers/dispDrvBase.h" +#include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h" +#include "drivers/dispDrvThinkInkGrayscale4T5.h" /*! @brief Interface for interacting with display hardware (TFT, eInk, diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index a01de88c0..638affe37 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index 9aad63649..9af63f69c 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 48d44bb8a..9e1339aec 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index 69a0aa023..b72968763 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -37,6 +37,7 @@ typedef enum _wippersnapper_display_v1_EPDColors { /* Struct definitions */ typedef struct _wippersnapper_display_v1_DisplayAddedorReplaced { + char name[64]; bool did_add; } wippersnapper_display_v1_DisplayAddedorReplaced; @@ -45,13 +46,12 @@ typedef struct _wippersnapper_display_v1_DisplayRemove { } wippersnapper_display_v1_DisplayRemove; typedef struct _wippersnapper_display_v1_DisplayRemoved { + char name[64]; bool did_remove; } wippersnapper_display_v1_DisplayRemoved; typedef struct _wippersnapper_display_v1_EPDConfig { wippersnapper_display_v1_EPDMode mode; - int32_t width; - int32_t height; } wippersnapper_display_v1_EPDConfig; typedef struct _wippersnapper_display_v1_EPDWriteOptions { @@ -111,29 +111,29 @@ extern "C" { /* Initializer values for message structs */ #define wippersnapper_display_v1_EpdSpiConfig_init_default {0, "", "", "", "", ""} -#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN, 0, 0} +#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN} #define wippersnapper_display_v1_EPDWriteOptions_init_default {0, _wippersnapper_display_v1_EPDColors_MIN} #define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} #define wippersnapper_display_v1_DisplayRemove_init_default {""} #define wippersnapper_display_v1_DisplayWrite_init_default {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_default}} -#define wippersnapper_display_v1_DisplayAddedorReplaced_init_default {0} -#define wippersnapper_display_v1_DisplayRemoved_init_default {0} +#define wippersnapper_display_v1_DisplayAddedorReplaced_init_default {"", 0} +#define wippersnapper_display_v1_DisplayRemoved_init_default {"", 0} #define wippersnapper_display_v1_EpdSpiConfig_init_zero {0, "", "", "", "", ""} -#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN, 0, 0} +#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN} #define wippersnapper_display_v1_EPDWriteOptions_init_zero {0, _wippersnapper_display_v1_EPDColors_MIN} #define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} #define wippersnapper_display_v1_DisplayRemove_init_zero {""} #define wippersnapper_display_v1_DisplayWrite_init_zero {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_zero}} -#define wippersnapper_display_v1_DisplayAddedorReplaced_init_zero {0} -#define wippersnapper_display_v1_DisplayRemoved_init_zero {0} +#define wippersnapper_display_v1_DisplayAddedorReplaced_init_zero {"", 0} +#define wippersnapper_display_v1_DisplayRemoved_init_zero {"", 0} /* Field tags (for use in manual encoding/decoding) */ -#define wippersnapper_display_v1_DisplayAddedorReplaced_did_add_tag 1 +#define wippersnapper_display_v1_DisplayAddedorReplaced_name_tag 1 +#define wippersnapper_display_v1_DisplayAddedorReplaced_did_add_tag 2 #define wippersnapper_display_v1_DisplayRemove_name_tag 1 -#define wippersnapper_display_v1_DisplayRemoved_did_remove_tag 1 +#define wippersnapper_display_v1_DisplayRemoved_name_tag 1 +#define wippersnapper_display_v1_DisplayRemoved_did_remove_tag 2 #define wippersnapper_display_v1_EPDConfig_mode_tag 1 -#define wippersnapper_display_v1_EPDConfig_width_tag 2 -#define wippersnapper_display_v1_EPDConfig_height_tag 3 #define wippersnapper_display_v1_EPDWriteOptions_text_size_tag 1 #define wippersnapper_display_v1_EPDWriteOptions_color_tag 2 #define wippersnapper_display_v1_EpdSpiConfig_bus_tag 1 @@ -162,9 +162,7 @@ X(a, STATIC, SINGULAR, STRING, pin_busy, 6) #define wippersnapper_display_v1_EpdSpiConfig_DEFAULT NULL #define wippersnapper_display_v1_EPDConfig_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UENUM, mode, 1) \ -X(a, STATIC, SINGULAR, INT32, width, 2) \ -X(a, STATIC, SINGULAR, INT32, height, 3) +X(a, STATIC, SINGULAR, UENUM, mode, 1) #define wippersnapper_display_v1_EPDConfig_CALLBACK NULL #define wippersnapper_display_v1_EPDConfig_DEFAULT NULL @@ -198,12 +196,14 @@ X(a, STATIC, ONEOF, MESSAGE, (options,epd_options,options.epd_options), #define wippersnapper_display_v1_DisplayWrite_options_epd_options_MSGTYPE wippersnapper_display_v1_EPDWriteOptions #define wippersnapper_display_v1_DisplayAddedorReplaced_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, did_add, 1) +X(a, STATIC, SINGULAR, STRING, name, 1) \ +X(a, STATIC, SINGULAR, BOOL, did_add, 2) #define wippersnapper_display_v1_DisplayAddedorReplaced_CALLBACK NULL #define wippersnapper_display_v1_DisplayAddedorReplaced_DEFAULT NULL #define wippersnapper_display_v1_DisplayRemoved_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, BOOL, did_remove, 1) +X(a, STATIC, SINGULAR, STRING, name, 1) \ +X(a, STATIC, SINGULAR, BOOL, did_remove, 2) #define wippersnapper_display_v1_DisplayRemoved_CALLBACK NULL #define wippersnapper_display_v1_DisplayRemoved_DEFAULT NULL @@ -228,13 +228,13 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; /* Maximum encoded size of messages (where known) */ #define wippersnapper_display_v1_EpdSpiConfig_size 46 -#define wippersnapper_display_v1_EPDConfig_size 24 +#define wippersnapper_display_v1_EPDConfig_size 2 #define wippersnapper_display_v1_EPDWriteOptions_size 13 -#define wippersnapper_display_v1_DisplayAddOrReplace_size 141 +#define wippersnapper_display_v1_DisplayAddOrReplace_size 119 #define wippersnapper_display_v1_DisplayRemove_size 65 #define wippersnapper_display_v1_DisplayWrite_size 1106 -#define wippersnapper_display_v1_DisplayAddedorReplaced_size 2 -#define wippersnapper_display_v1_DisplayRemoved_size 2 +#define wippersnapper_display_v1_DisplayAddedorReplaced_size 67 +#define wippersnapper_display_v1_DisplayRemoved_size 67 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index f95f752af..2033a041d 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index 112240f45..ba86dbb96 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index 88153e9d5..80c5b8c7e 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 5d2523e83..b2718e279 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 2aee561ac..11ba4661a 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index 5b635d492..28b37e0bb 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index d6beb4b79..cc1697451 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index 72e885682..8bb1815f4 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index 5649c2dd8..2cf59f201 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index 5b26ce7eb..12713219f 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index e012bc73f..bc08aa6ba 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index e285c9957..b9b62fe13 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index d4c6687bf..67dc1ade0 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 2a0997d57..77f6843a2 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED @@ -464,7 +464,7 @@ union wippersnapper_signal_v1_CreateSignalRequest_payload_size_union {char f6[(6 #define wippersnapper_signal_v1_PWMRequest_size 82 #define wippersnapper_signal_v1_PWMResponse_size 11 #define wippersnapper_signal_v1_DisplayRequest_size 1109 -#define wippersnapper_signal_v1_DisplayResponse_size 4 +#define wippersnapper_signal_v1_DisplayResponse_size 69 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index c81b97eee..27928dd4f 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index 4e7fa2a39..867abee65 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Tue Aug 19 17:48:25 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From 49cf9cc4bfd17f0a6cb8f7d8cc13c304f2e5917e Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Aug 2025 10:37:18 -0400 Subject: [PATCH 19/76] Detect SSD1680 automatically --- src/Wippersnapper.cpp | 54 ++++++----- src/components/display/drivers/dispDrvBase.h | 2 +- src/components/display/hardware.cpp | 95 +++++++++++++++++--- src/components/display/hardware.h | 5 +- 4 files changed, 116 insertions(+), 40 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 57d839b51..8cf7c9b7d 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -1684,30 +1684,38 @@ bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field, } // Attempt to add or replace a display component - bool did_add = WS._displayController->Handle_Display_AddOrReplace(&msgAddReq); - + bool did_add = + WS._displayController->Handle_Display_AddOrReplace(&msgAddReq); + // Create a DisplayResponse message - wippersnapper_signal_v1_DisplayResponse msgResp = wippersnapper_signal_v1_DisplayResponse_init_zero; - msgResp.which_payload = wippersnapper_signal_v1_DisplayResponse_display_added_tag; + wippersnapper_signal_v1_DisplayResponse msgResp = + wippersnapper_signal_v1_DisplayResponse_init_zero; + msgResp.which_payload = + wippersnapper_signal_v1_DisplayResponse_display_added_tag; msgResp.payload.display_added.did_add = did_add; - strncpy(msgResp.payload.display_added.name, msgAddReq.name, sizeof(msgResp.payload.display_added.name)); + strncpy(msgResp.payload.display_added.name, msgAddReq.name, + sizeof(msgResp.payload.display_added.name)); - // Encode and publish response back to broker - memset(WS._buffer_outgoing, 0, sizeof(WS._buffer_outgoing)); - pb_ostream_t ostream = pb_ostream_from_buffer(WS._buffer_outgoing, sizeof(WS._buffer_outgoing)); - if (!ws_pb_encode(&ostream, wippersnapper_signal_v1_DisplayResponse_fields, &msgResp)) { - WS_DEBUG_PRINTLN("ERROR: Unable to encode display response message!"); - return false; - } + // Encode and publish response back to broker + memset(WS._buffer_outgoing, 0, sizeof(WS._buffer_outgoing)); + pb_ostream_t ostream = pb_ostream_from_buffer(WS._buffer_outgoing, + sizeof(WS._buffer_outgoing)); + if (!ws_pb_encode(&ostream, wippersnapper_signal_v1_DisplayResponse_fields, + &msgResp)) { + WS_DEBUG_PRINTLN("ERROR: Unable to encode display response message!"); + return false; + } - size_t msgSz; - pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_DisplayResponse_fields, &msgResp); - WS_DEBUG_PRINT("Publishing DisplayResponse Message..."); - if (!WS._mqtt->publish(WS._topic_signal_display_device, WS._buffer_outgoing, msgSz, 1)) { - WS_DEBUG_PRINTLN("ERROR: Failed to DisplayResponse Response!"); - } else { - WS_DEBUG_PRINTLN("Published!"); - } + size_t msgSz; + pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_DisplayResponse_fields, + &msgResp); + WS_DEBUG_PRINT("Publishing DisplayResponse Message..."); + if (!WS._mqtt->publish(WS._topic_signal_display_device, WS._buffer_outgoing, + msgSz, 1)) { + WS_DEBUG_PRINTLN("ERROR: Failed to DisplayResponse Response!"); + } else { + WS_DEBUG_PRINTLN("Published!"); + } } else if (field->tag == wippersnapper_signal_v1_DisplayRequest_display_write_tag) { // Decode message into a DisplayAddRequest @@ -1720,12 +1728,12 @@ bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field, } // Attempt to write to a display WS._displayController->Handle_Display_Write(&msgWrite); - } else if (field->tag == wippersnapper_signal_v1_DisplayRequest_display_remove_tag) { + } else if (field->tag == + wippersnapper_signal_v1_DisplayRequest_display_remove_tag) { // Decode message into a DisplayRemoveRequest wippersnapper_display_v1_DisplayRemove msgRemove = wippersnapper_display_v1_DisplayRemove_init_zero; - if (!ws_pb_decode(stream, - wippersnapper_display_v1_DisplayRemove_fields, + if (!ws_pb_decode(stream, wippersnapper_display_v1_DisplayRemove_fields, &msgRemove)) { WS_DEBUG_PRINTLN("ERROR: Failure decoding DisplayRemove message!"); return false; diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index 9d50429da..c7d624836 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -15,8 +15,8 @@ #ifndef WS_DISP_DRV_BASE_H #define WS_DISP_DRV_BASE_H -#include "Wippersnapper.h" #include "Adafruit_ThinkInk.h" +#include "Wippersnapper.h" /*! @brief Abstract base class for display drivers. diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index eb34f8b8a..20ca62932 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -28,25 +28,12 @@ static const std::map FactoryDrvDisp = { int16_t busy) -> dispDrvBase * { return new drvDispThinkInkGrayscale4Eaamfgn(dc, rst, cs, sram_cs, busy); }}, - {"thinkink-magtag-2025", - [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, - int16_t busy) -> dispDrvBase * { - return new drvDispThinkInkGrayscale4Eaamfgn(dc, rst, cs, sram_cs, busy); - }}, {"thinkink-gs4-t5", [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, int16_t busy) -> dispDrvBase * { return new dispDrvThinkInkGrayscale4T5(dc, rst, cs, sram_cs, busy); - }}, - {"thinkink-magtag-pre-2025", - [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, - int16_t busy) -> dispDrvBase * { - return new dispDrvThinkInkGrayscale4T5(dc, rst, cs, sram_cs, busy); - }} - }; + }}}; - - /*! @brief Creates a new display driver instance based on the driver name. @param driver_name @@ -169,6 +156,19 @@ bool DisplayHardware::beginEPD( // TODO: Configure SPI bus selection (UNUSED AS OF RIGHT NOW) + // For "magtag" component name, attempt to autodetect the driver + if (strncmp(_name, "magtag", 6) == 0) { + if (detect_ssd1680(cs, dc, rst)) { + // Detected SSD1680, use EAAMFGN driver + strncpy(_name, "thinkink-gs4-eaamfgn", sizeof(_name) - 1); + _name[sizeof(_name) - 1] = '\0'; + } else { + // Did not detect SSD1680, use T5 driver + strncpy(_name, "thinkink-gs4-t5", sizeof(_name) - 1); + _name[sizeof(_name) - 1] = '\0'; + } + } + // Create display driver object using the factory function _drvDisp = CreateDrvDisp(_name, dc, rst, cs, srcs, busy); if (!_drvDisp) { @@ -210,4 +210,71 @@ void DisplayHardware::writeMessage(const char *message) { } else { WS_DEBUG_PRINTLN("[display] No display driver initialized!"); } +} + +/*! + @brief Detects if an SSD1680 EPD is connected using bit-banged SPI. + @param cs + Chip Select pin number. + @param dc + Data/Command pin number. + @param rst + Reset pin number. + @return True if an SSD1680 is detected, False otherwise (IL0373 or different + EPD). +*/ +bool DisplayHardware::detect_ssd1680(uint8_t cs, uint8_t dc, uint8_t rst) { + // note: for a complete implementation reference, see + // https://github.com/adafruit/circuitpython/commit/f4316cb2491c815b128acca47f1bb75519fe306e + // Configure SPI pins to bit-bang + pinMode(MOSI, OUTPUT); + pinMode(SCK, OUTPUT); + pinMode(cs, OUTPUT); + pinMode(dc, OUTPUT); + pinMode(rst, OUTPUT); + + // Begin transaction by pulling cs and dc LOW + digitalWrite(cs, LOW); + digitalWrite(dc, LOW); + digitalWrite(SCK, LOW); + digitalWrite(rst, HIGH); + + // Write to read register 0x71 + uint8_t cmd = 0x71; + for (int i = 0; i < 8; i++) { + digitalWrite(MOSI, (cmd & (1 << (7 - i))) != 0); + digitalWrite(SCK, HIGH); + digitalWrite(SCK, LOW); + } + + // Set DC high to indicate data and switch MOSI to input with PUR in case + // SSD1680 does not send data back + digitalWrite(dc, HIGH); + delayMicroseconds(1); + pinMode(MOSI, INPUT_PULLUP); + delayMicroseconds(1); + + // Read response from register + uint8_t status = 0; + for (int i = 0; i < 8; i++) { + status <<= 1; + if (digitalRead(MOSI)) { + status |= 1; + } + digitalWrite(SCK, HIGH); + delayMicroseconds(1); + digitalWrite(SCK, LOW); + delayMicroseconds(1); + } + + // End transaction by pulling CS high + digitalWrite(cs, HIGH); + + // Put back MOSI pin as an output + pinMode(MOSI, OUTPUT); + + WS_DEBUG_PRINT("[display] Bitbang read 0x71: 0x"); + WS_DEBUG_PRINTLN(status, HEX); + + return status == 0xFF; } \ No newline at end of file diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 00cba9625..f8f5dad61 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -15,11 +15,11 @@ #ifndef WS_DISPLAY_HARDWARE_H #define WS_DISPLAY_HARDWARE_H #include "Wippersnapper.h" -#include -#include #include "drivers/dispDrvBase.h" #include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h" #include "drivers/dispDrvThinkInkGrayscale4T5.h" +#include +#include /*! @brief Interface for interacting with display hardware (TFT, eInk, @@ -49,6 +49,7 @@ class DisplayHardware { void writeMessage(const char *message); private: + bool detect_ssd1680(uint8_t cs, uint8_t dc, uint8_t rst); char _name[64]; ///< Identifies the hardware instance wippersnapper_display_v1_DisplayType _type; ///< Display type dispDrvBase *_drvDisp = nullptr; ///< Base display driver From 1b9b634465622f03283569acb2dc47681aa1e6ea Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 21 Aug 2025 11:08:49 -0400 Subject: [PATCH 20/76] bump ver --- library.properties | 2 +- src/Wippersnapper.h | 2 +- src/components/display/controller.cpp | 8 +++----- src/components/display/hardware.cpp | 29 +++++++++++++++++---------- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/library.properties b/library.properties index e0e33a29c..5cf33a228 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Adafruit WipperSnapper -version=1.0.0-beta.111 +version=1.0.0-beta.112 author=Adafruit maintainer=Adafruit sentence=Arduino application for Adafruit.io WipperSnapper diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 758e97f2d..a487fc49e 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -151,7 +151,7 @@ #endif #define WS_VERSION \ - "1.0.0-beta.110" ///< WipperSnapper app. version (semver-formatted) + "1.0.0-beta.112" ///< WipperSnapper app. version (semver-formatted) // Reserved Adafruit IO MQTT topics #define TOPIC_IO_THROTTLE "/throttle" ///< Adafruit IO Throttle MQTT Topic diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index ebdef51c4..a5defae9f 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -17,9 +17,7 @@ /*! @brief Constructs a new DisplayController object */ -DisplayController::DisplayController() { - // TODO -} +DisplayController::DisplayController() {} /*! @brief Destructor @@ -68,7 +66,7 @@ bool DisplayController::Handle_Display_AddOrReplace( _hw_instances.push_back(display); // Store the display instance WS_DEBUG_PRINTLN("[display] Display added or replaced successfully!"); - return true; // Placeholder + return true; } /*! @@ -109,7 +107,7 @@ bool DisplayController::Handle_Display_Write( } } - // Early-out if display not found + // Early-out if driver instance not found if (!display) { WS_DEBUG_PRINTLN("[display] Failed to write, driver not found!"); return false; diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 20ca62932..13f8248da 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -119,11 +119,15 @@ bool DisplayHardware::beginEPD( // Validate mode is a correct EPD mode if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_UNSPECIFIED) { WS_DEBUG_PRINTLN("[display] Unsupported EPD mode!"); - return false; // Unsupported mode + return false; } - // TODO: If we already have a display driver assigned to this hardware - // instance, clean it up! + // If we already have a display driver assigned to this hardware instance, + // clean it up! + if (_drvDisp) { + delete _drvDisp; + _drvDisp = nullptr; + } // Parse all SPI bus pins // Check length @@ -154,16 +158,21 @@ bool DisplayHardware::beginEPD( busy = (int16_t)atoi(spi_config->pin_busy + 1); } - // TODO: Configure SPI bus selection (UNUSED AS OF RIGHT NOW) + // Configure SPI bus + if (spi_config->bus != 0) { + WS_DEBUG_PRINTLN( + "[display] ERROR: Non-default SPI buses are currently not supported!"); + return false; + } - // For "magtag" component name, attempt to autodetect the driver + // For "magtag" component name, attempt to autodetect the driver type if (strncmp(_name, "magtag", 6) == 0) { if (detect_ssd1680(cs, dc, rst)) { // Detected SSD1680, use EAAMFGN driver strncpy(_name, "thinkink-gs4-eaamfgn", sizeof(_name) - 1); _name[sizeof(_name) - 1] = '\0'; } else { - // Did not detect SSD1680, use T5 driver + // Did not detect SSD1680, use IL0373 driver strncpy(_name, "thinkink-gs4-t5", sizeof(_name) - 1); _name[sizeof(_name) - 1] = '\0'; } @@ -205,11 +214,9 @@ const char *DisplayHardware::getName() { return _name; } The message to display. */ void DisplayHardware::writeMessage(const char *message) { - if (_drvDisp) { - _drvDisp->writeMessage(message); - } else { - WS_DEBUG_PRINTLN("[display] No display driver initialized!"); - } + if (!_drvDisp) + return; + _drvDisp->writeMessage(message); } /*! From 82476b86591e3946098b4f5adb01132331aad3f0 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Aug 2025 11:13:20 -0400 Subject: [PATCH 21/76] Clang format --- src/Wippersnapper.h | 18 +++++------------- src/components/display/controller.cpp | 2 +- src/components/display/controller.h | 1 + .../drivers/dispDrvThinkInkGrayscale4T5.h | 7 ++++--- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index a487fc49e..e7af45ab7 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -47,24 +47,16 @@ // Define actual debug output functions when necessary. #ifdef WS_DEBUG #define WS_DEBUG_PRINT(...) \ - { \ - WS_PRINTER.print(__VA_ARGS__); \ - } ///< Prints debug output. + { WS_PRINTER.print(__VA_ARGS__); } ///< Prints debug output. #define WS_DEBUG_PRINTLN(...) \ - { \ - WS_PRINTER.println(__VA_ARGS__); \ - } ///< Prints line from debug output. + { WS_PRINTER.println(__VA_ARGS__); } ///< Prints line from debug output. #define WS_DEBUG_PRINTHEX(...) \ - { \ - WS_PRINTER.print(__VA_ARGS__, HEX); \ - } ///< Prints debug output. + { WS_PRINTER.print(__VA_ARGS__, HEX); } ///< Prints debug output. #else #define WS_DEBUG_PRINT(...) \ - { \ - } ///< Prints debug output + {} ///< Prints debug output #define WS_DEBUG_PRINTLN(...) \ - { \ - } ///< Prints line from debug output. + {} ///< Prints line from debug output. #endif #define WS_DELAY_WITH_WDT(timeout) \ diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index a5defae9f..476e898fd 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -25,7 +25,7 @@ DisplayController::DisplayController() {} DisplayController::~DisplayController() { // Clean up all display hardware instances for (DisplayHardware *hw_instance : _hw_instances) { - delete hw_instance; + delete hw_instance; } _hw_instances.clear(); } diff --git a/src/components/display/controller.h b/src/components/display/controller.h index 6dd3e4c05..f4c087e30 100644 --- a/src/components/display/controller.h +++ b/src/components/display/controller.h @@ -35,6 +35,7 @@ class DisplayController { wippersnapper_display_v1_DisplayAddOrReplace *msgAdd); bool Handle_Display_Remove(wippersnapper_display_v1_DisplayRemove *msgRemove); bool Handle_Display_Write(wippersnapper_display_v1_DisplayWrite *msgWrite); + private: std::vector _hw_instances; ///< Holds pointers to DisplayHardware instances diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h index 0320cf1eb..10978f245 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h @@ -19,7 +19,8 @@ #include "dispDrvBase.h" /*! - @brief Driver for a ThinkInk 2.9" Grayscale 4-level T5 display (pre-2025 version of the Adafruit MagTag). + @brief Driver for a ThinkInk 2.9" Grayscale 4-level T5 display (pre-2025 + version of the Adafruit MagTag). */ class dispDrvThinkInkGrayscale4T5 : public dispDrvBase { public: @@ -38,7 +39,7 @@ class dispDrvThinkInkGrayscale4T5 : public dispDrvBase { Optional Busy pin for the display. */ dispDrvThinkInkGrayscale4T5(int16_t dc, int16_t rst, int16_t cs, - int16_t sram_cs = -1, int16_t busy = -1) + int16_t sram_cs = -1, int16_t busy = -1) : dispDrvBase(dc, rst, cs, sram_cs, busy), _display(nullptr) {} ~dispDrvThinkInkGrayscale4T5() { @@ -59,7 +60,7 @@ class dispDrvThinkInkGrayscale4T5 : public dispDrvBase { */ bool begin(thinkinkmode_t mode, bool reset = true) override { _display = new ThinkInk_290_Grayscale4_T5(_pin_dc, _pin_rst, _pin_cs, - _pin_sram_cs, _pin_busy); + _pin_sram_cs, _pin_busy); if (!_display) return false; // Allocation failed From 3f9d05410e3399a3bb5db1fe9961485090902f80 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Aug 2025 11:29:06 -0400 Subject: [PATCH 22/76] doxy2 --- src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h index 10978f245..ed266e00b 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h @@ -1,5 +1,5 @@ /*! - * @file src/components/display/drivers/ThinkInk_290_Grayscale4_T5.h + * @file src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h * * Driver for ThinkInk 2.9" Grayscale 4-level T5 display (present on the * pre-2025 version of the Adafruit MagTag) From 0663d1d1bf5bc0136fb3b169ccbe70390a0be369 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 22 Aug 2025 11:41:17 -0400 Subject: [PATCH 23/76] Putback existing Doxyfile --- Doxyfile | 1207 +++++++++++++++++------------------------------------- 1 file changed, 373 insertions(+), 834 deletions(-) diff --git a/Doxyfile b/Doxyfile index 3de8ed0d8..2e9f261f9 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,7 +1,7 @@ -# Doxyfile 1.14.0 +# Doxyfile 1.9.1 # This file describes the settings to be used by the documentation system -# Doxygen (www.doxygen.org) for a project. +# doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. @@ -12,16 +12,6 @@ # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). -# -# Note: -# -# Use Doxygen to compare the used configuration file with the template -# configuration file: -# doxygen -x [configFile] -# Use Doxygen to compare the used configuration file with the template -# configuration file without replacing the environment variables or CMake type -# replacement variables: -# doxygen -x_noenv [configFile] #--------------------------------------------------------------------------- # Project related configuration options @@ -51,7 +41,7 @@ PROJECT_NAME = "Adafruit Library" PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewers a +# for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = @@ -63,42 +53,24 @@ PROJECT_BRIEF = PROJECT_LOGO = -# With the PROJECT_ICON tag one can specify an icon that is included in the tabs -# when the HTML document is shown. Doxygen will copy the logo to the output -# directory. - -PROJECT_ICON = - # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is -# entered, it will be relative to the location where Doxygen was started. If +# entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = -# If the CREATE_SUBDIRS tag is set to YES then Doxygen will create up to 4096 -# sub-directories (in 2 levels) under the output directory of each output format -# and will distribute the generated files over these directories. Enabling this -# option can be useful when feeding Doxygen a huge amount of source files, where -# putting all generated files in the same directory would otherwise cause -# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to -# control the number of sub-directories. +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO -# Controls the number of sub-directories that will be created when -# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every -# level increment doubles the number of directories, resulting in 4096 -# directories at level 8 which is the default and also the maximum value. The -# sub-directories are organized in 2 levels, the first level always has a fixed -# number of 16 directories. -# Minimum value: 0, maximum value: 8, default value: 8. -# This tag requires that the tag CREATE_SUBDIRS is set to YES. - -CREATE_SUBDIRS_LEVEL = 8 - -# If the ALLOW_UNICODE_NAMES tag is set to YES, Doxygen will allow non-ASCII +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. @@ -107,28 +79,28 @@ CREATE_SUBDIRS_LEVEL = 8 ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all -# documentation generated by Doxygen is written. Doxygen will use this +# documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian, -# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English -# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek, -# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with -# English messages), Korean, Korean-en (Korean with English messages), Latvian, -# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, -# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, -# Swedish, Turkish, Ukrainian and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES, Doxygen will include brief member +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES, Doxygen will prepend the brief +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the @@ -159,13 +131,13 @@ ABBREVIATE_BRIEF = "The $name class" \ the # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO -# If the INLINE_INHERITED_MEMB tag is set to YES, Doxygen will show all +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. @@ -173,7 +145,7 @@ ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES, Doxygen will prepend the full path +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. @@ -183,11 +155,11 @@ FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which Doxygen is run is used as the path to +# If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which -# will be relative from the directory where Doxygen is started. +# will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = @@ -201,42 +173,31 @@ STRIP_FROM_PATH = STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, Doxygen will generate much shorter (but -# less readable) file names. This can be useful if your file system doesn't +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen will interpret the -# first line (until the first dot, question mark or exclamation mark) of a -# Javadoc-style comment as the brief description. If set to NO, the Javadoc- -# style will behave just like regular Qt-style comments (thus requiring an -# explicit @brief command for a brief description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO -# If the JAVADOC_BANNER tag is set to YES then Doxygen will interpret a line -# such as -# /*************** -# as being the beginning of a Javadoc-style comment "banner". If set to NO, the -# Javadoc-style will behave just like regular comments and it will not be -# interpreted by Doxygen. -# The default value is: NO. - -JAVADOC_BANNER = NO - -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will interpret the first -# line (until the first dot, question mark or exclamation mark) of a Qt-style -# comment as the brief description. If set to NO, the Qt-style will behave just -# like regular Qt-style comments (thus requiring an explicit \brief command for -# a brief description.) +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen treat a +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this @@ -248,21 +209,13 @@ QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO -# By default Python docstrings are displayed as preformatted text and Doxygen's -# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the -# Doxygen's special commands can be used and the contents of the docstring -# documentation blocks is shown as Doxygen documentation. -# The default value is: YES. - -PYTHON_DOCSTRING = YES - # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES then Doxygen will produce a new +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. @@ -279,16 +232,16 @@ TAB_SIZE = 4 # the documentation. An alias has the form: # name=value # For example adding -# "sideeffect=@par Side Effects:^^" +# "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading -# "Side Effects:". Note that you cannot put \n's in the value part of an alias -# to insert newlines (in the resulting output). You can put ^^ in the value part -# of an alias to insert a newline as if a physical newline was in the original -# file. When you need a literal { or } or , in the value part of an alias you -# have to escape them by means of a backslash (\), this can lead to conflicts -# with the commands \{ and \} for these it is advised to use the version @{ and -# @} or use a double escape (\\{ and \\}) +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) ALIASES = @@ -320,42 +273,34 @@ OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO -# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice -# sources only. Doxygen will then generate output that is more tailored for that -# language. For instance, namespaces will be presented as modules, types will be -# separated into more groups, etc. -# The default value is: NO. - -OPTIMIZE_OUTPUT_SLICE = NO - # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and -# language is one of the parsers supported by Doxygen: IDL, Java, JavaScript, -# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice, -# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: # FortranFree, unknown formatted Fortran: Fortran. In the later case the parser # tries to guess whether the code is fixed or free formatted code, this is the -# default for Fortran type files). For instance to make Doxygen treat .inc files +# default for Fortran type files). For instance to make doxygen treat .inc files # as Fortran files (default is PHP), and .f files as C (default is Fortran), # use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise -# the files are not read by Doxygen. When specifying no_extension you should add +# the files are not read by doxygen. When specifying no_extension you should add # * to the FILE_PATTERNS. # # Note see also the list of default file extension mappings. EXTENSION_MAPPING = -# If the MARKDOWN_SUPPORT tag is enabled then Doxygen pre-processes all comments +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See https://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by Doxygen, so you can -# mix Doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. @@ -365,45 +310,25 @@ MARKDOWN_SUPPORT = YES # to that level are automatically included in the table of contents, even if # they do not have an id attribute. # Note: This feature currently applies only to Markdown headings. -# Minimum value: 0, maximum value: 99, default value: 6. +# Minimum value: 0, maximum value: 99, default value: 5. # This tag requires that the tag MARKDOWN_SUPPORT is set to YES. TOC_INCLUDE_HEADINGS = 0 -# The MARKDOWN_ID_STYLE tag can be used to specify the algorithm used to -# generate identifiers for the Markdown headings. Note: Every identifier is -# unique. -# Possible values are: DOXYGEN use a fixed 'autotoc_md' string followed by a -# sequence number starting at 0 and GITHUB use the lower case version of title -# with any whitespace replaced by '-' and punctuation characters removed. -# The default value is: DOXYGEN. -# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. - -MARKDOWN_ID_STYLE = DOXYGEN - -# When enabled Doxygen tries to link words that correspond to documented +# When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. Words listed in the -# AUTOLINK_IGNORE_WORDS tag are excluded from automatic linking. +# globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES -# This tag specifies a list of words that, when matching the start of a word in -# the documentation, will suppress auto links generation, if it is enabled via -# AUTOLINK_SUPPORT. This list does not affect links explicitly created using \# -# or the \link or commands. -# This tag requires that the tag AUTOLINK_SUPPORT is set to YES. - -AUTOLINK_IGNORE_WORDS = - # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this -# tag to YES in order to let Doxygen match functions declarations and +# tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); -# versus func(std::string) {}). This also makes the inheritance and -# collaboration diagrams that involve STL classes more complete and accurate. +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO @@ -415,16 +340,16 @@ BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: -# https://www.riverbankcomputing.com/software) sources only. Doxygen will parse -# them like normal C++ but will assume all classes use public instead of private -# inheritance when no explicit protection keyword is present. +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make -# Doxygen to replace the get and set methods by a property in the documentation. +# doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. @@ -433,7 +358,7 @@ SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES then Doxygen will reuse the documentation of the first +# tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. @@ -491,42 +416,21 @@ TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the -# code, Doxygen keeps a cache of pre-resolved symbols. If the cache is too small -# Doxygen will become slower. If the cache is too large, memory is wasted. The +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 -# symbols. At the end of a run Doxygen will report the cache usage and suggest +# symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 -# The NUM_PROC_THREADS specifies the number of threads Doxygen is allowed to use -# during processing. When set to 0 Doxygen will based this on the number of -# cores available in the system. You can set it explicitly to a value larger -# than 0 to get more control over the balance between CPU load and processing -# speed. At this moment only the input processing can be done using multiple -# threads. Since this is still an experimental feature the default is set to 1, -# which effectively disables parallel processing. Please report any issues you -# encounter. Generating dot graphs in parallel is controlled by the -# DOT_NUM_THREADS setting. -# Minimum value: 0, maximum value: 32, default value: 1. - -NUM_PROC_THREADS = 1 - -# If the TIMESTAMP tag is set different from NO then each generated page will -# contain the date or date and time when the page was generated. Setting this to -# NO can help when comparing the output of multiple runs. -# Possible values are: YES, NO, DATETIME and DATE. -# The default value is: NO. - -TIMESTAMP = NO - #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES, Doxygen will assume all entities in +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. @@ -542,12 +446,6 @@ EXTRACT_ALL = NO EXTRACT_PRIVATE = NO -# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual -# methods of a class will be included in the documentation. -# The default value is: NO. - -EXTRACT_PRIV_VIRTUAL = NO - # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. @@ -585,14 +483,7 @@ EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO -# If this flag is set to YES, the name of an unnamed parameter in a declaration -# will be determined by the corresponding definition. By default unnamed -# parameters remain unnamed in the output. -# The default value is: YES. - -RESOLVE_UNNAMED_PARAMS = YES - -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. @@ -600,31 +491,22 @@ RESOLVE_UNNAMED_PARAMS = YES HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option -# will also hide undocumented C++ concepts if enabled. This option has no effect -# if EXTRACT_ALL is enabled. +# has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO -# If the HIDE_UNDOC_NAMESPACES tag is set to YES, Doxygen will hide all -# undocumented namespaces that are normally visible in the namespace hierarchy. -# If set to NO, these namespaces will be included in the various overviews. This -# option has no effect if EXTRACT_ALL is enabled. -# The default value is: YES. - -HIDE_UNDOC_NAMESPACES = YES - -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all friend +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # declarations. If set to NO, these declarations will be included in the # documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. @@ -638,44 +520,37 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO -# With the correct setting of option CASE_SENSE_NAMES Doxygen will better be +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be # able to match the capabilities of the underlying filesystem. In case the # filesystem is case sensitive (i.e. it supports files in the same directory # whose names only differ in casing), the option must be set to YES to properly # deal with such files in case they appear in the input. For filesystems that -# are not case sensitive the option should be set to NO to properly deal with +# are not case sensitive the option should be be set to NO to properly deal with # output files written for symbols that only differ in casing, such as for two # classes, one named CLASS and the other named Class, and to also support # references to files without having to specify the exact matching casing. On -# Windows (including Cygwin) and macOS, users should typically set this option +# Windows (including Cygwin) and MacOS, users should typically set this option # to NO, whereas on Linux or other Unix flavors it should typically be set to # YES. -# Possible values are: SYSTEM, NO and YES. -# The default value is: SYSTEM. +# The default value is: system dependent. CASE_SENSE_NAMES = NO -# If the HIDE_SCOPE_NAMES tag is set to NO then Doxygen will show members with +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO -# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then Doxygen will +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO -# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class -# will show which file needs to be included to use the class. -# The default value is: YES. - -SHOW_HEADERFILE = YES - -# If the SHOW_INCLUDE_FILES tag is set to YES then Doxygen will put a list of +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. @@ -688,7 +563,7 @@ SHOW_INCLUDE_FILES = YES SHOW_GROUPED_MEMB_INC = NO -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen will list include +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. @@ -700,14 +575,14 @@ FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES then Doxygen will sort the +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = NO -# If the SORT_BRIEF_DOCS tag is set to YES then Doxygen will sort the brief +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. @@ -715,7 +590,7 @@ SORT_MEMBER_DOCS = NO SORT_BRIEF_DOCS = NO -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then Doxygen will sort the +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. @@ -727,7 +602,7 @@ SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO -# If the SORT_GROUP_NAMES tag is set to YES then Doxygen will sort the hierarchy +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. @@ -744,11 +619,11 @@ SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO -# If the STRICT_PROTO_MATCHING option is enabled and Doxygen fails to do proper +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a -# simple string match. By disabling STRICT_PROTO_MATCHING Doxygen will still +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. @@ -818,25 +693,24 @@ SHOW_FILES = YES SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that -# Doxygen should invoke to get the current version for each file (typically from +# doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided -# by Doxygen. Whatever the program writes to standard output is used as the file +# by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed -# by Doxygen. The layout file controls the global structure of the generated +# by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file -# that represents Doxygen's defaults, run Doxygen with the -l option. You can +# that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml -# will be used as the name of the layout file. See also section "Changing the -# layout of pages" for information. +# will be used as the name of the layout file. # -# Note that if you run Doxygen from a directory containing a file called -# DoxygenLayout.xml, Doxygen will parse it automatically even if the LAYOUT_FILE +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = @@ -851,35 +725,19 @@ LAYOUT_FILE = CITE_BIB_FILES = -# The EXTERNAL_TOOL_PATH tag can be used to extend the search path (PATH -# environment variable) so that external tools such as latex and gs can be -# found. -# Note: Directories specified with EXTERNAL_TOOL_PATH are added in front of the -# path already specified by the PATH variable, and are added in the order -# specified. -# Note: This option is particularly useful for macOS version 14 (Sonoma) and -# higher, when running Doxygen from Doxywizard, because in this case any user- -# defined changes to the PATH are ignored. A typical example on macOS is to set -# EXTERNAL_TOOL_PATH = /Library/TeX/texbin /usr/local/bin -# together with the standard path, the full search path used by doxygen when -# launching external tools will then become -# PATH=/Library/TeX/texbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin - -EXTERNAL_TOOL_PATH = - #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to -# standard output by Doxygen. If QUIET is set to YES this implies that the +# standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error (stderr) by Doxygen. If WARNINGS is set to YES +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. @@ -887,97 +745,52 @@ QUIET = YES WARNINGS = YES -# If the WARN_IF_UNDOCUMENTED tag is set to YES then Doxygen will generate +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES -# If the WARN_IF_DOC_ERROR tag is set to YES, Doxygen will generate warnings for -# potential errors in the documentation, such as documenting some parameters in -# a documented function twice, or documenting parameters that don't exist or -# using markup commands wrongly. +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES -# If WARN_IF_INCOMPLETE_DOC is set to YES, Doxygen will warn about incomplete -# function parameter documentation. If set to NO, Doxygen will accept that some -# parameters have no documentation without warning. -# The default value is: YES. - -WARN_IF_INCOMPLETE_DOC = YES - # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return -# value. If set to NO, Doxygen will only warn about wrong parameter -# documentation, but not about the absence of documentation. If EXTRACT_ALL is -# set to YES then this flag will automatically be disabled. See also -# WARN_IF_INCOMPLETE_DOC +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. # The default value is: NO. WARN_NO_PARAMDOC = YES -# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, Doxygen will warn about -# undocumented enumeration values. If set to NO, Doxygen will accept -# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag -# will automatically be disabled. -# The default value is: NO. - -WARN_IF_UNDOC_ENUM_VAL = NO - -# If WARN_LAYOUT_FILE option is set to YES, Doxygen will warn about issues found -# while parsing the user defined layout file, such as missing or wrong elements. -# See also LAYOUT_FILE for details. If set to NO, problems with the layout file -# will be suppressed. -# The default value is: YES. - -WARN_LAYOUT_FILE = YES - -# If the WARN_AS_ERROR tag is set to YES then Doxygen will immediately stop when +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS -# then Doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but -# at the end of the Doxygen process Doxygen will return with a non-zero status. -# If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS_PRINT then Doxygen behaves -# like FAIL_ON_WARNINGS but in case no WARN_LOGFILE is defined Doxygen will not -# write the warning messages in between other messages but write them at the end -# of a run, in case a WARN_LOGFILE is defined the warning messages will be -# besides being in the defined file also be shown at the end of a run, unless -# the WARN_LOGFILE is defined as - i.e. standard output (stdout) in that case -# the behavior will remain as with the setting FAIL_ON_WARNINGS. -# Possible values are: NO, YES, FAIL_ON_WARNINGS and FAIL_ON_WARNINGS_PRINT. +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. # The default value is: NO. WARN_AS_ERROR = NO -# The WARN_FORMAT tag determines the format of the warning messages that Doxygen +# The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) -# See also: WARN_LINE_FORMAT # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" -# In the $text part of the WARN_FORMAT command it is possible that a reference -# to a more specific place is given. To make it easier to jump to this place -# (outside of Doxygen) the user can define a custom "cut" / "paste" string. -# Example: -# WARN_LINE_FORMAT = "'vi $file +$line'" -# See also: WARN_FORMAT -# The default value is: at line $line of file $file. - -WARN_LINE_FORMAT = "at line $line of file $file" - # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard -# error (stderr). In case the file specified cannot be opened for writing the -# warning and error messages are written to standard error. When as file - is -# specified the warning and error messages are written to standard output -# (stdout). +# error (stderr). WARN_LOGFILE = @@ -994,42 +807,31 @@ WARN_LOGFILE = INPUT = # This tag can be used to specify the character encoding of the source files -# that Doxygen parses. Internally Doxygen uses the UTF-8 encoding. Doxygen uses +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: # https://www.gnu.org/software/libiconv/) for the list of possible encodings. -# See also: INPUT_FILE_ENCODING # The default value is: UTF-8. INPUT_ENCODING = UTF-8 -# This tag can be used to specify the character encoding of the source files -# that Doxygen parses. The INPUT_FILE_ENCODING tag can be used to specify -# character encoding on a per file pattern basis. Doxygen will compare the file -# name with each pattern and apply the encoding instead of the default -# INPUT_ENCODING if there is a match. The character encodings are a list of the -# form: pattern=encoding (like *.php=ISO-8859-1). -# See also: INPUT_ENCODING for further information on supported encodings. - -INPUT_FILE_ENCODING = - # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not -# read by Doxygen. +# read by doxygen. # # Note the list of default checked file patterns might differ from the list of # default file extension mappings. # -# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cxxm, -# *.cpp, *.cppm, *.ccm, *.c++, *.c++m, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, -# *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, -# *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be -# provided as Doxygen C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, -# *.f18, *.f, *.for, *.vhd, *.vhdl, *.ucf, *.qsf and *.ice. +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, +# *.ucf, *.qsf and *.ice. FILE_PATTERNS = *.c \ *.cc \ @@ -1052,7 +854,7 @@ RECURSIVE = YES # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # -# Note that relative paths are relative to the directory from which Doxygen is +# Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = EXCLUDE \ @@ -1083,7 +885,10 @@ EXCLUDE_PATTERNS = *.md # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, -# ANamespace::AClass, ANamespace::*Test +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = @@ -1113,7 +918,7 @@ EXAMPLE_RECURSIVE = NO IMAGE_PATH = -# The INPUT_FILTER tag can be used to specify a program that Doxygen should +# The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # @@ -1128,14 +933,9 @@ IMAGE_PATH = # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # -# Note that Doxygen will use the data processed and written to standard output -# for further processing, therefore nothing else, like debug statements or used -# commands (so in case of a Windows batch file always use @echo OFF), should be -# written to standard output. -# # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by Doxygen. +# properly processed by doxygen. INPUT_FILTER = @@ -1148,7 +948,7 @@ INPUT_FILTER = # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not -# properly processed by Doxygen. +# properly processed by doxygen. FILTER_PATTERNS = @@ -1170,28 +970,10 @@ FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub -# and want to reuse the introduction page also for the Doxygen output. +# and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = -# If the IMPLICIT_DIR_DOCS tag is set to YES, any README.md file found in sub- -# directories of the project's root, is used as the documentation for that sub- -# directory, except when the README.md starts with a \dir, \page or \mainpage -# command. If set to NO, the README.md file needs to start with an explicit \dir -# command in order to be used as directory documentation. -# The default value is: YES. - -IMPLICIT_DIR_DOCS = YES - -# The Fortran standard specifies that for fixed formatted Fortran code all -# characters from position 72 are to be considered as comment. A common -# extension is to allow longer lines before the automatic comment starts. The -# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can -# be processed before the automatic comment starts. -# Minimum value: 7, maximum value: 10000, default value: 72. - -FORTRAN_COMMENT_AFTER = 72 - #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- @@ -1206,13 +988,12 @@ FORTRAN_COMMENT_AFTER = 72 SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, -# multi-line macros, enums or list initialized variables directly into the -# documentation. +# classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES will instruct Doxygen to hide any +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. @@ -1250,7 +1031,7 @@ REFERENCES_LINK_SOURCE = YES SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will -# point to the HTML generated by the htags(1) tool instead of Doxygen built-in +# point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see https://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. @@ -1264,14 +1045,14 @@ SOURCE_TOOLTIPS = YES # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # -# The result: instead of the source browser generated by Doxygen, the links to +# The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set the YES then Doxygen will generate a +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. @@ -1290,11 +1071,10 @@ VERBATIM_HEADERS = YES ALPHABETICAL_INDEX = YES -# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes) -# that should be ignored while generating the index headers. The IGNORE_PREFIX -# tag works for classes, function and member names. The entity will be placed in -# the alphabetical list under the first letter of the entity name that remains -# after removing the prefix. +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = @@ -1303,7 +1083,7 @@ IGNORE_PREFIX = # Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES, Doxygen will generate HTML output +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES @@ -1324,40 +1104,40 @@ HTML_OUTPUT = html HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for -# each generated HTML page. If the tag is left blank Doxygen will generate a +# each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets -# that Doxygen needs, which is dependent on the configuration options used (e.g. +# that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" -# for information on how to generate the default header that Doxygen normally +# for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of Doxygen. For a description +# default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each -# generated HTML page. If the tag is left blank Doxygen will generate a standard +# generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer -# that Doxygen normally uses. +# that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of -# the HTML output. If left blank Doxygen will generate a default style sheet. +# the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style -# sheet that Doxygen normally uses. +# sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. @@ -1367,18 +1147,13 @@ HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets -# created by Doxygen. Using this option one can overrule certain style aspects. +# created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the -# list). -# Note: Since the styling of scrollbars can currently not be overruled in -# Webkit/Chromium, the styling will be left out of the default doxygen.css if -# one or more extra stylesheets have been specified. So if scrollbar -# customization is desired it has to be added explicitly. For an example see the -# documentation. +# list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = @@ -1393,22 +1168,9 @@ HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = -# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output -# should be rendered with a dark or light theme. -# Possible values are: LIGHT always generates light mode output, DARK always -# generates dark mode output, AUTO_LIGHT automatically sets the mode according -# to the user preference, uses light mode if no preference is set (the default), -# AUTO_DARK automatically sets the mode according to the user preference, uses -# dark mode if no preference is set and TOGGLE allows a user to switch between -# light and dark mode via a button. -# The default value is: AUTO_LIGHT. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COLORSTYLE = AUTO_LIGHT - # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to -# this color. Hue is specified as an angle on a color-wheel, see +# this color. Hue is specified as an angle on a colorwheel, see # https://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. @@ -1418,7 +1180,7 @@ HTML_COLORSTYLE = AUTO_LIGHT HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors -# in the HTML output. For a value of 0 the output will use gray-scales only. A +# in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1436,16 +1198,14 @@ HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 -# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML -# documentation will contain a main index with vertical navigation menus that -# are dynamically created via JavaScript. If disabled, the navigation index will -# consists of multiple levels of tabs that are statically embedded in every HTML -# page. Disable this option to support browsers that do not have JavaScript, -# like the Qt help browser. -# The default value is: YES. +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_DYNAMIC_MENUS = YES +HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the @@ -1455,33 +1215,6 @@ HTML_DYNAMIC_MENUS = YES HTML_DYNAMIC_SECTIONS = NO -# If the HTML_CODE_FOLDING tag is set to YES then classes and functions can be -# dynamically folded and expanded in the generated HTML source code. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_CODE_FOLDING = YES - -# If the HTML_COPY_CLIPBOARD tag is set to YES then Doxygen will show an icon in -# the top right corner of code and text fragments that allows the user to copy -# its content to the clipboard. Note this only works if supported by the browser -# and the web page is served via a secure context (see: -# https://www.w3.org/TR/secure-contexts/), i.e. using the https: or file: -# protocol. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_COPY_CLIPBOARD = YES - -# Doxygen stores a couple of settings persistently in the browser (via e.g. -# cookies). By default these settings apply to all HTML pages generated by -# Doxygen across all projects. The HTML_PROJECT_COOKIE tag can be used to store -# the settings under a project specific key, such that the user preferences will -# be stored separately. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_PROJECT_COOKIE = - # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to @@ -1499,7 +1232,7 @@ HTML_INDEX_NUM_ENTRIES = 100 # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: # https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To -# create a documentation set, Doxygen will generate a Makefile in the HTML +# create a documentation set, doxygen will generate a Makefile in the HTML # output directory. Running make will produce the docset in that directory and # running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at @@ -1518,13 +1251,6 @@ GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" -# This tag determines the URL of the docset feed. A documentation feed provides -# an umbrella under which multiple documentation sets from a single provider -# (such as a company or product suite) can be grouped. -# This tag requires that the tag GENERATE_DOCSET is set to YES. - -DOCSET_FEEDURL = - # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. @@ -1547,18 +1273,14 @@ DOCSET_PUBLISHER_ID = org.doxygen.Publisher DOCSET_PUBLISHER_NAME = Publisher -# If the GENERATE_HTMLHELP tag is set to YES then Doxygen generates three +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop -# on Windows. In the beginning of 2021 Microsoft took the original page, with -# a.o. the download links, offline (the HTML help workshop was already many -# years in maintenance mode). You can download the HTML help workshop from the -# web archives at Installation executable (see: -# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo -# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe). +# (see: +# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output -# generated by Doxygen into a single compiled HTML file (.chm). Compiled HTML +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for @@ -1578,7 +1300,7 @@ CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, -# Doxygen will try to run the HTML help compiler on the generated index.hhp. +# doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1612,16 +1334,6 @@ BINARY_TOC = NO TOC_EXPAND = NO -# The SITEMAP_URL tag is used to specify the full URL of the place where the -# generated documentation will be placed on the server by the user during the -# deployment of the documentation. The generated sitemap is called sitemap.xml -# and placed on the directory specified by HTML_OUTPUT. In case no SITEMAP_URL -# is specified no sitemap is generated. For information about the sitemap -# protocol see https://www.sitemaps.org -# This tag requires that the tag GENERATE_HTML is set to YES. - -SITEMAP_URL = - # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help @@ -1680,7 +1392,7 @@ QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location (absolute path -# including file name) of Qt's qhelpgenerator. If non-empty Doxygen will try to +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to # run qhelpgenerator on the generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. @@ -1724,39 +1436,18 @@ DISABLE_INDEX = NO # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can -# further fine tune the look of the index (see "Fine-tuning the output"). As an -# example, the default style sheet generated by Doxygen has an example that -# shows how to put an image at the root of the tree instead of the PROJECT_NAME. -# Since the tree basically has more details information than the tab index, you -# could consider setting DISABLE_INDEX to YES when enabling this option. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -GENERATE_TREEVIEW = NO - -# When GENERATE_TREEVIEW is set to YES, the PAGE_OUTLINE_PANEL option determines -# if an additional navigation panel is shown at the right hand side of the -# screen, displaying an outline of the contents of the main page, similar to -# e.g. https://developer.android.com/reference If GENERATE_TREEVIEW is set to -# NO, this option has no effect. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -PAGE_OUTLINE_PANEL = YES - -# When GENERATE_TREEVIEW is set to YES, the FULL_SIDEBAR option determines if -# the side bar is limited to only the treeview area (value NO) or if it should -# extend to the full height of the window (value YES). Setting this to YES gives -# a layout similar to e.g. https://docs.readthedocs.io with more room for -# contents, but less room for the project logo, title, and description. If -# GENERATE_TREEVIEW is set to NO, this option has no effect. +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -FULL_SIDEBAR = NO +GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that -# Doxygen will group on one line in the generated HTML documentation. +# doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. @@ -1765,12 +1456,6 @@ FULL_SIDEBAR = NO ENUM_VALUES_PER_LINE = 4 -# When the SHOW_ENUM_VALUES tag is set doxygen will show the specified -# enumeration values besides the enumeration mnemonics. -# The default value is: NO. - -SHOW_ENUM_VALUES = NO - # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. @@ -1778,45 +1463,32 @@ SHOW_ENUM_VALUES = NO TREEVIEW_WIDTH = 250 -# If the EXT_LINKS_IN_WINDOW option is set to YES, Doxygen will open links to +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO -# If the OBFUSCATE_EMAILS tag is set to YES, Doxygen will obfuscate email -# addresses. -# The default value is: YES. -# This tag requires that the tag GENERATE_HTML is set to YES. - -OBFUSCATE_EMAILS = YES - -# If the HTML_FORMULA_FORMAT option is set to svg, Doxygen will use the pdf2svg -# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see -# https://inkscape.org) to generate formulas as SVG images instead of PNGs for -# the HTML output. These images will generally look nicer at scaled resolutions. -# Possible values are: png (the default) and svg (looks nicer but requires the -# pdf2svg or inkscape tool). -# The default value is: png. -# This tag requires that the tag GENERATE_HTML is set to YES. - -HTML_FORMULA_FORMAT = png - # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful -# Doxygen run you need to manually remove any form_*.png images from the HTML +# doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 -# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands -# to create new LaTeX commands to be used in formulas as building blocks. See -# the section "Including formulas" for details. +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. -FORMULA_MACROFILE = +FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # https://www.mathjax.org) which uses client side JavaScript for the rendering @@ -1829,29 +1501,11 @@ FORMULA_MACROFILE = USE_MATHJAX = NO -# With MATHJAX_VERSION it is possible to specify the MathJax version to be used. -# Note that the different versions of MathJax have different requirements with -# regards to the different settings, so it is possible that also other MathJax -# settings have to be changed when switching between the different MathJax -# versions. -# Possible values are: MathJax_2 and MathJax_3. -# The default value is: MathJax_2. -# This tag requires that the tag USE_MATHJAX is set to YES. - -MATHJAX_VERSION = MathJax_2 - # When MathJax is enabled you can set the default output format to be used for -# the MathJax output. For more details about the output format see MathJax -# version 2 (see: -# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3 -# (see: -# http://docs.mathjax.org/en/latest/web/components/output.html). +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best -# compatibility. This is the name for Mathjax version 2, for MathJax version 3 -# this will be translated into chtml), NativeMML (i.e. MathML. Only supported -# for MathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This -# is the name for Mathjax version 3, for MathJax version 2 this will be -# translated into HTML-CSS) and SVG. +# compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. @@ -1864,26 +1518,20 @@ MATHJAX_FORMAT = HTML-CSS # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of -# MathJax from https://www.mathjax.org before deployment. The default value is: -# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2 -# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3 +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example -# for MathJax version 2 (see -# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions): # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols -# For example for MathJax version 3 (see -# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html): -# MATHJAX_EXTENSIONS = ams # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = -# The MATHJAX_CODEFILE tag can be used to specify a file with JavaScript pieces +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: # http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an @@ -1892,12 +1540,12 @@ MATHJAX_EXTENSIONS = MATHJAX_CODEFILE = -# When the SEARCHENGINE tag is enabled Doxygen will generate a search box for -# the HTML output. The underlying search engine uses JavaScript and DHTML and +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. -# For large projects the JavaScript based search engine can be slow, then +# For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically @@ -1916,7 +1564,7 @@ SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using JavaScript. There # are two flavors of web server based searching depending on the EXTERNAL_SEARCH -# setting. When disabled, Doxygen will generate a PHP script for searching and +# setting. When disabled, doxygen will generate a PHP script for searching and # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing # and searching needs to be provided by external tools. See the section # "External Indexing and Searching" for details. @@ -1925,7 +1573,7 @@ SEARCHENGINE = YES SERVER_BASED_SEARCH = NO -# When EXTERNAL_SEARCH tag is enabled Doxygen will no longer generate the PHP +# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP # script for searching. Instead the search results are written to an XML file # which needs to be processed by an external indexer. Doxygen will invoke an # external search engine pointed to by the SEARCHENGINE_URL option to obtain the @@ -1970,7 +1618,7 @@ SEARCHDATA_FILE = searchdata.xml EXTERNAL_SEARCH_ID = -# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through Doxygen +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen # projects other than the one defined by this configuration file, but that are # all added to the same external search index. Each project needs to have a # unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of @@ -1984,7 +1632,7 @@ EXTRA_SEARCH_MAPPINGS = # Configuration options related to the LaTeX output #--------------------------------------------------------------------------- -# If the GENERATE_LATEX tag is set to YES, Doxygen will generate LaTeX output. +# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. # The default value is: YES. GENERATE_LATEX = NO @@ -2019,17 +1667,7 @@ LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex -# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to -# generate index for LaTeX. In case there is no backslash (\) as first character -# it will be automatically added in the LaTeX code. -# Note: This tag is used in the generated output file (.tex). -# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat. -# The default value is: makeindex. -# This tag requires that the tag GENERATE_LATEX is set to YES. - -LATEX_MAKEINDEX_CMD = makeindex - -# If the COMPACT_LATEX tag is set to YES, Doxygen generates more compact LaTeX +# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX # documents. This may be useful for small projects and may help to save some # trees in general. # The default value is: NO. @@ -2058,38 +1696,36 @@ PAPER_TYPE = a4 EXTRA_PACKAGES = -# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for -# the generated LaTeX document. The header should contain everything until the -# first chapter. If it is left blank Doxygen will generate a standard header. It -# is highly recommended to start with a default header using -# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty -# and then modify the file new_header.tex. See also section "Doxygen usage" for -# information on how to generate the default header that Doxygen normally uses. +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the +# generated LaTeX document. The header should contain everything until the first +# chapter. If it is left blank doxygen will generate a standard header. See +# section "Doxygen usage" for information on how to let doxygen write the +# default header to a separate file. # -# Note: Only use a user-defined header if you know what you are doing! -# Note: The header is subject to change so you typically have to regenerate the -# default header when upgrading to a newer version of Doxygen. The following -# commands have a special meaning inside the header (and footer): For a -# description of the possible markers and block names see the documentation. +# Note: Only use a user-defined header if you know what you are doing! The +# following commands have a special meaning inside the header: $title, +# $datetime, $date, $doxygenversion, $projectname, $projectnumber, +# $projectbrief, $projectlogo. Doxygen will replace $title with the empty +# string, for the replacement values of the other commands the user is referred +# to HTML_HEADER. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HEADER = -# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for -# the generated LaTeX document. The footer should contain everything after the -# last chapter. If it is left blank Doxygen will generate a standard footer. See +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the +# generated LaTeX document. The footer should contain everything after the last +# chapter. If it is left blank doxygen will generate a standard footer. See # LATEX_HEADER for more information on how to generate a default footer and what -# special commands can be used inside the footer. See also section "Doxygen -# usage" for information on how to generate the default footer that Doxygen -# normally uses. Note: Only use a user-defined footer if you know what you are -# doing! +# special commands can be used inside the footer. +# +# Note: Only use a user-defined footer if you know what you are doing! # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_FOOTER = # The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined # LaTeX style sheets that are included after the standard style sheets created -# by Doxygen. Using this option one can overrule certain style aspects. Doxygen +# by doxygen. Using this option one can overrule certain style aspects. Doxygen # will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the @@ -2115,7 +1751,7 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES -# If the USE_PDFLATEX tag is set to YES, Doxygen will use the engine as +# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as # specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX # files. Set this option to YES, to get a higher quality PDF documentation. # @@ -2125,49 +1761,53 @@ PDF_HYPERLINKS = YES USE_PDFLATEX = YES -# The LATEX_BATCHMODE tag signals the behavior of LaTeX in case of an error. -# Possible values are: NO same as ERROR_STOP, YES same as BATCH, BATCH In batch -# mode nothing is printed on the terminal, errors are scrolled as if is -# hit at every error; missing files that TeX tries to input or request from -# keyboard input (\read on a not open input stream) cause the job to abort, -# NON_STOP In nonstop mode the diagnostic message will appear on the terminal, -# but there is no possibility of user interaction just like in batch mode, -# SCROLL In scroll mode, TeX will stop only for missing files to input or if -# keyboard input is necessary and ERROR_STOP In errorstop mode, TeX will stop at -# each error, asking for user intervention. +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode +# command to the generated LaTeX files. This will instruct LaTeX to keep running +# if errors occur, instead of asking the user for help. This option is also used +# when generating formulas in HTML. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_BATCHMODE = NO -# If the LATEX_HIDE_INDICES tag is set to YES then Doxygen will not include the +# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the # index chapters (such as File Index, Compound Index, etc.) in the output. # The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_HIDE_INDICES = NO +# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source +# code with syntax highlighting in the LaTeX output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_SOURCE_CODE = NO + # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. See # https://en.wikipedia.org/wiki/BibTeX and \cite for more info. -# The default value is: plainnat. +# The default value is: plain. # This tag requires that the tag GENERATE_LATEX is set to YES. LATEX_BIB_STYLE = plain -# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) -# path from which the emoji images will be read. If a relative path is entered, -# it will be relative to the LATEX_OUTPUT directory. If left blank the -# LATEX_OUTPUT directory will be used. +# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: NO. # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_EMOJI_DIRECTORY = +LATEX_TIMESTAMP = NO #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- -# If the GENERATE_RTF tag is set to YES, Doxygen will generate RTF output. The +# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The # RTF output is optimized for Word 97 and may not look too pretty with other RTF # readers/editors. # The default value is: NO. @@ -2182,7 +1822,7 @@ GENERATE_RTF = NO RTF_OUTPUT = rtf -# If the COMPACT_RTF tag is set to YES, Doxygen generates more compact RTF +# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF # documents. This may be useful for small projects and may help to save some # trees in general. # The default value is: NO. @@ -2202,36 +1842,38 @@ COMPACT_RTF = NO RTF_HYPERLINKS = NO -# Load stylesheet definitions from file. Syntax is similar to Doxygen's +# Load stylesheet definitions from file. Syntax is similar to doxygen's # configuration file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. # # See also section "Doxygen usage" for information on how to generate the -# default style sheet that Doxygen normally uses. +# default style sheet that doxygen normally uses. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an RTF document. Syntax is -# similar to Doxygen's configuration file. A template extensions file can be +# similar to doxygen's configuration file. A template extensions file can be # generated using doxygen -e rtf extensionFile. # This tag requires that the tag GENERATE_RTF is set to YES. RTF_EXTENSIONS_FILE = -# The RTF_EXTRA_FILES tag can be used to specify one or more extra images or -# other source files which should be copied to the RTF_OUTPUT output directory. -# Note that the files will be copied as-is; there are no commands or markers -# available. +# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code +# with syntax highlighting in the RTF output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. # This tag requires that the tag GENERATE_RTF is set to YES. -RTF_EXTRA_FILES = +RTF_SOURCE_CODE = NO #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- -# If the GENERATE_MAN tag is set to YES, Doxygen will generate man pages for +# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for # classes and files. # The default value is: NO. @@ -2262,7 +1904,7 @@ MAN_EXTENSION = .3 MAN_SUBDIR = -# If the MAN_LINKS tag is set to YES and Doxygen generates man output, then it +# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it # will generate one additional man file for each entity documented in the real # man page(s). These additional files only source the real man page, but without # them the man command would be unable to find the correct page. @@ -2275,7 +1917,7 @@ MAN_LINKS = NO # Configuration options related to the XML output #--------------------------------------------------------------------------- -# If the GENERATE_XML tag is set to YES, Doxygen will generate an XML file that +# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that # captures the structure of the code including all documentation. # The default value is: NO. @@ -2289,7 +1931,7 @@ GENERATE_XML = NO XML_OUTPUT = xml -# If the XML_PROGRAMLISTING tag is set to YES, Doxygen will dump the program +# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program # listings (including syntax highlighting and cross-referencing information) to # the XML output. Note that enabling this will significantly increase the size # of the XML output. @@ -2298,18 +1940,11 @@ XML_OUTPUT = xml XML_PROGRAMLISTING = YES -# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, Doxygen will include -# namespace members in file scope as well, matching the HTML output. -# The default value is: NO. -# This tag requires that the tag GENERATE_XML is set to YES. - -XML_NS_MEMB_FILE_SCOPE = NO - #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- -# If the GENERATE_DOCBOOK tag is set to YES, Doxygen will generate Docbook files +# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files # that can be used to generate PDF. # The default value is: NO. @@ -2323,49 +1958,32 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook +# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the +# program listings (including syntax highlighting and cross-referencing +# information) to the DOCBOOK output. Note that enabling this will significantly +# increase the size of the DOCBOOK output. +# The default value is: NO. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_PROGRAMLISTING = NO + #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- -# If the GENERATE_AUTOGEN_DEF tag is set to YES, Doxygen will generate an -# AutoGen Definitions (see https://autogen.sourceforge.net/) file that captures +# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an +# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures # the structure of the code including all documentation. Note that this feature # is still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# Configuration options related to Sqlite3 output -#--------------------------------------------------------------------------- - -# If the GENERATE_SQLITE3 tag is set to YES Doxygen will generate a Sqlite3 -# database with symbols found by Doxygen stored in tables. -# The default value is: NO. - -GENERATE_SQLITE3 = NO - -# The SQLITE3_OUTPUT tag is used to specify where the Sqlite3 database will be -# put. If a relative path is entered the value of OUTPUT_DIRECTORY will be put -# in front of it. -# The default directory is: sqlite3. -# This tag requires that the tag GENERATE_SQLITE3 is set to YES. - -SQLITE3_OUTPUT = sqlite3 - -# The SQLITE3_RECREATE_DB tag is set to YES, the existing doxygen_sqlite3.db -# database file will be recreated with each Doxygen run. If set to NO, Doxygen -# will warn if a database file is already found and not modify it. -# The default value is: YES. -# This tag requires that the tag GENERATE_SQLITE3 is set to YES. - -SQLITE3_RECREATE_DB = YES - #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- -# If the GENERATE_PERLMOD tag is set to YES, Doxygen will generate a Perl module +# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module # file that captures the structure of the code including all documentation. # # Note that this feature is still experimental and incomplete at the moment. @@ -2373,7 +1991,7 @@ SQLITE3_RECREATE_DB = YES GENERATE_PERLMOD = NO -# If the PERLMOD_LATEX tag is set to YES, Doxygen will generate the necessary +# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary # Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI # output from the Perl module output. # The default value is: NO. @@ -2403,13 +2021,13 @@ PERLMOD_MAKEVAR_PREFIX = # Configuration options related to the preprocessor #--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES, Doxygen will evaluate all +# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all # C-preprocessor directives found in the sources and include files. # The default value is: YES. ENABLE_PREPROCESSING = YES -# If the MACRO_EXPANSION tag is set to YES, Doxygen will expand all macro names +# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names # in the source code. If set to NO, only conditional compilation will be # performed. Macro expansion can be done in a controlled way by setting # EXPAND_ONLY_PREDEF to YES. @@ -2435,8 +2053,7 @@ SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by the -# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of -# RECURSIVE has no effect here. +# preprocessor. # This tag requires that the tag SEARCH_INCLUDES is set to YES. INCLUDE_PATH = @@ -2457,9 +2074,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = "__cdecl=," \ - "ARDUINO_ARCH_ESP32=1," \ - ARDUINO_FUNHOUSE_ESP32S2=1 +PREDEFINED = __cdecl=, ARDUINO_ARCH_ESP32=1, ARDUINO_FUNHOUSE_ESP32S2=1 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -2470,7 +2085,7 @@ PREDEFINED = "__cdecl=," \ EXPAND_AS_DEFINED = -# If the SKIP_FUNCTION_MACROS tag is set to YES then Doxygen's preprocessor will +# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will # remove all references to function-like macros that are alone on a line, have # an all uppercase name, and do not end with a semicolon. Such function macros # are typically used for boiler-plate code, and will confuse the parser if not @@ -2494,26 +2109,26 @@ SKIP_FUNCTION_MACROS = YES # section "Linking to external documentation" for more information about the use # of tag files. # Note: Each tag file must have a unique name (where the name does NOT include -# the path). If a tag file is not located in the directory in which Doxygen is +# the path). If a tag file is not located in the directory in which doxygen is # run, you must also specify the path to the tagfile here. TAGFILES = -# When a file name is specified after GENERATE_TAGFILE, Doxygen will create a +# When a file name is specified after GENERATE_TAGFILE, doxygen will create a # tag file that is based on the input files it reads. See section "Linking to # external documentation" for more information about the usage of tag files. GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES, all external classes and namespaces -# will be listed in the class and namespace index. If set to NO, only the -# inherited external classes will be listed. +# If the ALLEXTERNALS tag is set to YES, all external class will be listed in +# the class index. If set to NO, only the inherited external classes will be +# listed. # The default value is: NO. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed -# in the topic index. If set to NO, only the current project's groups will be +# in the modules index. If set to NO, only the current project's groups will be # listed. # The default value is: YES. @@ -2527,26 +2142,42 @@ EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES #--------------------------------------------------------------------------- -# Configuration options related to diagram generator tools +# Configuration options related to the dot tool #--------------------------------------------------------------------------- +# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram +# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to +# NO turns the diagrams off. Note that this option also works with HAVE_DOT +# disabled, but it is recommended to install and use dot, since it yields more +# powerful graphs. +# The default value is: YES. + +CLASS_DIAGRAMS = YES + +# You can include diagrams made with dia in doxygen documentation. Doxygen will +# then run dia to produce the diagram and insert it in the documentation. The +# DIA_PATH tag allows you to specify the directory where the dia binary resides. +# If left empty dia is assumed to be found in the default search path. + +DIA_PATH = + # If set to YES the inheritance and collaboration graphs will hide inheritance # and usage relations if the target is undocumented or is not a class. # The default value is: YES. HIDE_UNDOC_RELATIONS = YES -# If you set the HAVE_DOT tag to YES then Doxygen will assume the dot tool is +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz (see: -# https://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # Bell Labs. The other options in this section have no effect if this option is # set to NO # The default value is: NO. HAVE_DOT = NO -# The DOT_NUM_THREADS specifies the number of dot invocations Doxygen is allowed -# to run in parallel. When set to 0 Doxygen will base this on the number of +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed +# to run in parallel. When set to 0 doxygen will base this on the number of # processors available in the system. You can set it explicitly to a value # larger than 0 to get control over the balance between CPU load and processing # speed. @@ -2555,83 +2186,55 @@ HAVE_DOT = NO DOT_NUM_THREADS = 0 -# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of -# subgraphs. When you want a differently looking font in the dot files that -# Doxygen generates you can specify fontname, fontcolor and fontsize attributes. -# For details please see Node, -# Edge and Graph Attributes specification You need to make sure dot is able -# to find the font, which can be done by putting it in a standard location or by -# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the -# directory containing the font. Default graphviz fontsize is 14. -# The default value is: fontname=Helvetica,fontsize=10. +# When you want a differently looking font in the dot files that doxygen +# generates you can specify the font name using DOT_FONTNAME. You need to make +# sure dot is able to find the font, which can be done by putting it in a +# standard location or by setting the DOTFONTPATH environment variable or by +# setting DOT_FONTPATH to the directory containing the font. +# The default value is: Helvetica. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_COMMON_ATTR = "fontname=Helvetica,fontsize=10" +DOT_FONTNAME = Helvetica -# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can -# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. Complete documentation about -# arrows shapes. -# The default value is: labelfontname=Helvetica,labelfontsize=10. +# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of +# dot graphs. +# Minimum value: 4, maximum value: 24, default value: 10. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_EDGE_ATTR = "labelfontname=Helvetica,labelfontsize=10" +DOT_FONTSIZE = 10 -# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes -# around nodes set 'shape=plain' or 'shape=plaintext' Shapes specification -# The default value is: shape=box,height=0.2,width=0.4. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_NODE_ATTR = "shape=box,height=0.2,width=0.4" - -# You can set the path where dot can find font specified with fontname in -# DOT_COMMON_ATTR and others dot attributes. +# By default doxygen will tell dot to use the default font as specified with +# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set +# the path where dot can find it using this tag. # This tag requires that the tag HAVE_DOT is set to YES. DOT_FONTPATH = -# If the CLASS_GRAPH tag is set to YES or GRAPH or BUILTIN then Doxygen will -# generate a graph for each documented class showing the direct and indirect -# inheritance relations. In case the CLASS_GRAPH tag is set to YES or GRAPH and -# HAVE_DOT is enabled as well, then dot will be used to draw the graph. In case -# the CLASS_GRAPH tag is set to YES and HAVE_DOT is disabled or if the -# CLASS_GRAPH tag is set to BUILTIN, then the built-in generator will be used. -# If the CLASS_GRAPH tag is set to TEXT the direct and indirect inheritance -# relations will be shown as texts / links. Explicit enabling an inheritance -# graph or choosing a different representation for an inheritance graph of a -# specific class, can be accomplished by means of the command \inheritancegraph. -# Disabling an inheritance graph can be accomplished by means of the command -# \hideinheritancegraph. -# Possible values are: NO, YES, TEXT, GRAPH and BUILTIN. +# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for +# each documented class showing the direct and indirect inheritance relations. +# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. # The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. CLASS_GRAPH = YES -# If the COLLABORATION_GRAPH tag is set to YES then Doxygen will generate a +# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a # graph for each documented class showing the direct and indirect implementation # dependencies (inheritance, containment, and class references variables) of the -# class with other documented classes. Explicit enabling a collaboration graph, -# when COLLABORATION_GRAPH is set to NO, can be accomplished by means of the -# command \collaborationgraph. Disabling a collaboration graph can be -# accomplished by means of the command \hidecollaborationgraph. +# class with other documented classes. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. COLLABORATION_GRAPH = YES -# If the GROUP_GRAPHS tag is set to YES then Doxygen will generate a graph for -# groups, showing the direct groups dependencies. Explicit enabling a group -# dependency graph, when GROUP_GRAPHS is set to NO, can be accomplished by means -# of the command \groupgraph. Disabling a directory graph can be accomplished by -# means of the command \hidegroupgraph. See also the chapter Grouping in the -# manual. +# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for +# groups, showing the direct groups dependencies. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GROUP_GRAPHS = YES -# If the UML_LOOK tag is set to YES, Doxygen will generate inheritance and +# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. # The default value is: NO. @@ -2652,37 +2255,6 @@ UML_LOOK = NO UML_LIMIT_NUM_FIELDS = 10 -# If the UML_LOOK tag is enabled, field labels are shown along the edge between -# two class nodes. If there are many fields and many nodes the graph may become -# too cluttered. The UML_MAX_EDGE_LABELS threshold limits the number of items to -# make the size more manageable. Set this to 0 for no limit. -# Minimum value: 0, maximum value: 100, default value: 10. -# This tag requires that the tag UML_LOOK is set to YES. - -UML_MAX_EDGE_LABELS = 10 - -# If the DOT_UML_DETAILS tag is set to NO, Doxygen will show attributes and -# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS -# tag is set to YES, Doxygen will add type and arguments for attributes and -# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, Doxygen -# will not generate fields with class member information in the UML graphs. The -# class diagrams will look similar to the default class diagrams but using UML -# notation for the relationships. -# Possible values are: NO, YES and NONE. -# The default value is: NO. -# This tag requires that the tag UML_LOOK is set to YES. - -DOT_UML_DETAILS = NO - -# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters -# to display on a single line. If the actual line length exceeds this threshold -# significantly it will be wrapped across multiple lines. Some heuristics are -# applied to avoid ugly line breaks. -# Minimum value: 0, maximum value: 1000, default value: 17. -# This tag requires that the tag HAVE_DOT is set to YES. - -DOT_WRAP_THRESHOLD = 17 - # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and # collaboration graphs will show the relations between templates and their # instances. @@ -2692,29 +2264,24 @@ DOT_WRAP_THRESHOLD = 17 TEMPLATE_RELATIONS = NO # If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to -# YES then Doxygen will generate a graph for each documented file showing the +# YES then doxygen will generate a graph for each documented file showing the # direct and indirect include dependencies of the file with other documented -# files. Explicit enabling an include graph, when INCLUDE_GRAPH is is set to NO, -# can be accomplished by means of the command \includegraph. Disabling an -# include graph can be accomplished by means of the command \hideincludegraph. +# files. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. INCLUDE_GRAPH = YES # If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are -# set to YES then Doxygen will generate a graph for each documented file showing +# set to YES then doxygen will generate a graph for each documented file showing # the direct and indirect include dependencies of the file with other documented -# files. Explicit enabling an included by graph, when INCLUDED_BY_GRAPH is set -# to NO, can be accomplished by means of the command \includedbygraph. Disabling -# an included by graph can be accomplished by means of the command -# \hideincludedbygraph. +# files. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. INCLUDED_BY_GRAPH = YES -# If the CALL_GRAPH tag is set to YES then Doxygen will generate a call +# If the CALL_GRAPH tag is set to YES then doxygen will generate a call # dependency graph for every global function or class method. # # Note that enabling this option will significantly increase the time of a run. @@ -2726,7 +2293,7 @@ INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO -# If the CALLER_GRAPH tag is set to YES then Doxygen will generate a caller +# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller # dependency graph for every global function or class method. # # Note that enabling this option will significantly increase the time of a run. @@ -2738,59 +2305,44 @@ CALL_GRAPH = NO CALLER_GRAPH = NO -# If the GRAPHICAL_HIERARCHY tag is set to YES then Doxygen will graphical +# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical # hierarchy of all classes instead of a textual one. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GRAPHICAL_HIERARCHY = YES -# If the DIRECTORY_GRAPH tag is set to YES then Doxygen will show the +# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the # dependencies a directory has on other directories in a graphical way. The # dependency relations are determined by the #include relations between the -# files in the directories. Explicit enabling a directory graph, when -# DIRECTORY_GRAPH is set to NO, can be accomplished by means of the command -# \directorygraph. Disabling a directory graph can be accomplished by means of -# the command \hidedirectorygraph. +# files in the directories. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. DIRECTORY_GRAPH = YES -# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels -# of child directories generated in directory dependency graphs by dot. -# Minimum value: 1, maximum value: 25, default value: 1. -# This tag requires that the tag DIRECTORY_GRAPH is set to YES. - -DIR_GRAPH_MAX_DEPTH = 1 - # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. For an explanation of the image formats see the section # output formats in the documentation of the dot tool (Graphviz (see: -# https://www.graphviz.org/)). -# -# Note the formats svg:cairo and svg:cairo:cairo cannot be used in combination -# with INTERACTIVE_SVG (the INTERACTIVE_SVG will be set to NO). +# http://www.graphviz.org/)). +# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order +# to make the SVG files visible in IE 9+ (other browsers do not have this +# requirement). # Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo, -# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus, -# png:gdiplus:gdiplus, svg:cairo, svg:cairo:cairo, svg:svg, svg:svg:core, -# gif:cairo, gif:cairo:gd, gif:cairo:gdiplus, gif:gdiplus, gif:gdiplus:gdiplus, -# gif:gd, gif:gd:gd, jpg:cairo, jpg:cairo:gd, jpg:cairo:gdiplus, jpg:gd, -# jpg:gd:gd, jpg:gdiplus and jpg:gdiplus:gdiplus. +# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and +# png:gdiplus:gdiplus. # The default value is: png. # This tag requires that the tag HAVE_DOT is set to YES. DOT_IMAGE_FORMAT = png -# If DOT_IMAGE_FORMAT is set to svg or svg:svg or svg:svg:core, then this option -# can be set to YES to enable generation of interactive SVG images that allow -# zooming and panning. +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. # # Note that this requires a modern browser other than Internet Explorer. Tested # and working are Firefox, Chrome, Safari, and Opera. -# -# Note This option will be automatically disabled when DOT_IMAGE_FORMAT is set -# to svg:cairo or svg:cairo:cairo. +# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make +# the SVG files visible. Older versions of IE do not have SVG support. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2809,12 +2361,11 @@ DOT_PATH = DOTFILE_DIRS = -# You can include diagrams made with dia in Doxygen documentation. Doxygen will -# then run dia to produce the diagram and insert it in the documentation. The -# DIA_PATH tag allows you to specify the directory where the dia binary resides. -# If left empty dia is assumed to be found in the default search path. +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). -DIA_PATH = +MSCFILE_DIRS = # The DIAFILE_DIRS tag can be used to specify one or more directories that # contain dia files that are included in the documentation (see the \diafile @@ -2822,34 +2373,28 @@ DIA_PATH = DIAFILE_DIRS = -# When using PlantUML, the PLANTUML_JAR_PATH tag should be used to specify the -# path where java can find the plantuml.jar file or to the filename of jar file -# to be used. If left blank, it is assumed PlantUML is not used or called during -# a preprocessing step. Doxygen will generate a warning when it encounters a -# \startuml command in this case and will not generate output for the diagram. +# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the +# path where java can find the plantuml.jar file. If left blank, it is assumed +# PlantUML is not used or called during a preprocessing step. Doxygen will +# generate a warning when it encounters a \startuml command in this case and +# will not generate output for the diagram. PLANTUML_JAR_PATH = -# When using PlantUML, the PLANTUML_CFG_FILE tag can be used to specify a -# configuration file for PlantUML. +# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for plantuml. PLANTUML_CFG_FILE = -# When using PlantUML, the specified paths are searched for files specified by -# the !include statement in a PlantUML block. +# When using plantuml, the specified paths are searched for files specified by +# the !include statement in a plantuml block. PLANTUML_INCLUDE_PATH = -# The PLANTUMLFILE_DIRS tag can be used to specify one or more directories that -# contain PlantUml files that are included in the documentation (see the -# \plantumlfile command). - -PLANTUMLFILE_DIRS = - # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes # that will be shown in the graph. If the number of nodes in a graph becomes -# larger than this value, Doxygen will truncate the graph, which is visualized -# by representing a node as a red box. Note that if the number of direct +# larger than this value, doxygen will truncate the graph, which is visualized +# by representing a node as a red box. Note that doxygen if the number of direct # children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that # the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. @@ -2870,6 +2415,18 @@ DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not seem +# to support this out of the box. +# +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_TRANSPARENT = NO + # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) support @@ -2879,37 +2436,19 @@ MAX_DOT_GRAPH_DEPTH = 0 DOT_MULTI_TARGETS = NO -# If the GENERATE_LEGEND tag is set to YES Doxygen will generate a legend page +# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page # explaining the meaning of the various boxes and arrows in the dot generated # graphs. -# Note: This tag requires that UML_LOOK isn't set, i.e. the Doxygen internal -# graphical representation for inheritance and collaboration diagrams is used. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES, Doxygen will remove the intermediate +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate # files that are used to generate the various graphs. # -# Note: This setting is not only used for dot files but also for msc temporary -# files. +# Note: This setting is not only used for dot files but also for msc and +# plantuml temporary files. # The default value is: YES. -DOT_CLEANUP = YES - -# You can define message sequence charts within Doxygen comments using the \msc -# command. If the MSCGEN_TOOL tag is left empty (the default), then Doxygen will -# use a built-in version of mscgen tool to produce the charts. Alternatively, -# the MSCGEN_TOOL tag can also specify the name an external tool. For instance, -# specifying prog as the value, Doxygen will call the tool as prog -T -# -o . The external tool should support -# output file formats "png", "eps", "svg", and "ismap". - -MSCGEN_TOOL = - -# The MSCFILE_DIRS tag can be used to specify one or more directories that -# contain msc files that are included in the documentation (see the \mscfile -# command). - -MSCFILE_DIRS = +DOT_CLEANUP = YES \ No newline at end of file From 3636761d5cf95dd30ad2fbc587ca3d383ecb44e1 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 25 Aug 2025 11:29:41 -0400 Subject: [PATCH 24/76] checkin 615ef8c..fbc883c --- platformio.ini | 2 +- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 9 +- src/wippersnapper/display/v1/display.pb.h | 102 +++++++++++++----- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 4 +- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 21 files changed, 100 insertions(+), 51 deletions(-) diff --git a/platformio.ini b/platformio.ini index 25bbc006b..904558804 100644 --- a/platformio.ini +++ b/platformio.ini @@ -101,7 +101,7 @@ lib_deps = https://github.com/Starmbi/hp_BH1750.git https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git Adafruit EPD - + Adafruit ST7735 and ST7789 Library ; Common build environment for ESP32 platform diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index 638affe37..d9c9db34a 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index 9af63f69c..f931c6f89 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 9e1339aec..b056ffec4 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -15,6 +15,12 @@ PB_BIND(wippersnapper_display_v1_EPDConfig, wippersnapper_display_v1_EPDConfig, PB_BIND(wippersnapper_display_v1_EPDWriteOptions, wippersnapper_display_v1_EPDWriteOptions, AUTO) +PB_BIND(wippersnapper_display_v1_TftSpiConfig, wippersnapper_display_v1_TftSpiConfig, AUTO) + + +PB_BIND(wippersnapper_display_v1_TftConfig, wippersnapper_display_v1_TftConfig, AUTO) + + PB_BIND(wippersnapper_display_v1_DisplayAddOrReplace, wippersnapper_display_v1_DisplayAddOrReplace, AUTO) @@ -33,4 +39,3 @@ PB_BIND(wippersnapper_display_v1_DisplayRemoved, wippersnapper_display_v1_Displa - diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index b72968763..2ab870c13 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -24,17 +24,6 @@ typedef enum _wippersnapper_display_v1_EPDMode { wippersnapper_display_v1_EPDMode_EPD_MODE_MONO = 2 } wippersnapper_display_v1_EPDMode; -typedef enum _wippersnapper_display_v1_EPDColors { - wippersnapper_display_v1_EPDColors_EPD_COLORS_UNSPECIFIED = 0, - wippersnapper_display_v1_EPDColors_EPD_COLORS_WHITE = 1, - wippersnapper_display_v1_EPDColors_EPD_COLORS_BLACK = 2, - wippersnapper_display_v1_EPDColors_EPD_COLORS_RED = 3, - wippersnapper_display_v1_EPDColors_EPD_COLORS_GRAY = 4, - wippersnapper_display_v1_EPDColors_EPD_COLORS_DARK = 5, - wippersnapper_display_v1_EPDColors_EPD_COLORS_LIGHT = 6, - wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW = 7 -} wippersnapper_display_v1_EPDColors; - /* Struct definitions */ typedef struct _wippersnapper_display_v1_DisplayAddedorReplaced { char name[64]; @@ -56,7 +45,6 @@ typedef struct _wippersnapper_display_v1_EPDConfig { typedef struct _wippersnapper_display_v1_EPDWriteOptions { int32_t text_size; - wippersnapper_display_v1_EPDColors color; } wippersnapper_display_v1_EPDWriteOptions; typedef struct _wippersnapper_display_v1_EpdSpiConfig { @@ -68,16 +56,34 @@ typedef struct _wippersnapper_display_v1_EpdSpiConfig { char pin_busy[6]; } wippersnapper_display_v1_EpdSpiConfig; +typedef struct _wippersnapper_display_v1_TftConfig { + int32_t width; + int32_t height; + int32_t rotation; +} wippersnapper_display_v1_TftConfig; + +typedef struct _wippersnapper_display_v1_TftSpiConfig { + int32_t bus; + char pin_cs[6]; + char pin_dc[6]; + char pin_mosi[6]; + char pin_sck[6]; + char pin_rst[6]; + char pin_miso[6]; +} wippersnapper_display_v1_TftSpiConfig; + typedef struct _wippersnapper_display_v1_DisplayAddOrReplace { wippersnapper_display_v1_DisplayType type; char name[64]; pb_size_t which_interface_type; union { wippersnapper_display_v1_EpdSpiConfig spi_epd; + wippersnapper_display_v1_TftSpiConfig spi_tft; } interface_type; pb_size_t which_config; union { - wippersnapper_display_v1_EPDConfig epd_config; + wippersnapper_display_v1_EPDConfig config_epd; + wippersnapper_display_v1_TftConfig config_tft; } config; } wippersnapper_display_v1_DisplayAddOrReplace; @@ -100,10 +106,6 @@ typedef struct _wippersnapper_display_v1_DisplayWrite { #define _wippersnapper_display_v1_EPDMode_MAX wippersnapper_display_v1_EPDMode_EPD_MODE_MONO #define _wippersnapper_display_v1_EPDMode_ARRAYSIZE ((wippersnapper_display_v1_EPDMode)(wippersnapper_display_v1_EPDMode_EPD_MODE_MONO+1)) -#define _wippersnapper_display_v1_EPDColors_MIN wippersnapper_display_v1_EPDColors_EPD_COLORS_UNSPECIFIED -#define _wippersnapper_display_v1_EPDColors_MAX wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW -#define _wippersnapper_display_v1_EPDColors_ARRAYSIZE ((wippersnapper_display_v1_EPDColors)(wippersnapper_display_v1_EPDColors_EPD_COLORS_YELLOW+1)) - #ifdef __cplusplus extern "C" { @@ -112,7 +114,9 @@ extern "C" { /* Initializer values for message structs */ #define wippersnapper_display_v1_EpdSpiConfig_init_default {0, "", "", "", "", ""} #define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN} -#define wippersnapper_display_v1_EPDWriteOptions_init_default {0, _wippersnapper_display_v1_EPDColors_MIN} +#define wippersnapper_display_v1_EPDWriteOptions_init_default {0} +#define wippersnapper_display_v1_TftSpiConfig_init_default {0, "", "", "", "", "", ""} +#define wippersnapper_display_v1_TftConfig_init_default {0, 0, 0} #define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} #define wippersnapper_display_v1_DisplayRemove_init_default {""} #define wippersnapper_display_v1_DisplayWrite_init_default {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_default}} @@ -120,7 +124,9 @@ extern "C" { #define wippersnapper_display_v1_DisplayRemoved_init_default {"", 0} #define wippersnapper_display_v1_EpdSpiConfig_init_zero {0, "", "", "", "", ""} #define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN} -#define wippersnapper_display_v1_EPDWriteOptions_init_zero {0, _wippersnapper_display_v1_EPDColors_MIN} +#define wippersnapper_display_v1_EPDWriteOptions_init_zero {0} +#define wippersnapper_display_v1_TftSpiConfig_init_zero {0, "", "", "", "", "", ""} +#define wippersnapper_display_v1_TftConfig_init_zero {0, 0, 0} #define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} #define wippersnapper_display_v1_DisplayRemove_init_zero {""} #define wippersnapper_display_v1_DisplayWrite_init_zero {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_zero}} @@ -135,17 +141,28 @@ extern "C" { #define wippersnapper_display_v1_DisplayRemoved_did_remove_tag 2 #define wippersnapper_display_v1_EPDConfig_mode_tag 1 #define wippersnapper_display_v1_EPDWriteOptions_text_size_tag 1 -#define wippersnapper_display_v1_EPDWriteOptions_color_tag 2 #define wippersnapper_display_v1_EpdSpiConfig_bus_tag 1 #define wippersnapper_display_v1_EpdSpiConfig_pin_dc_tag 2 #define wippersnapper_display_v1_EpdSpiConfig_pin_rst_tag 3 #define wippersnapper_display_v1_EpdSpiConfig_pin_cs_tag 4 #define wippersnapper_display_v1_EpdSpiConfig_pin_sram_cs_tag 5 #define wippersnapper_display_v1_EpdSpiConfig_pin_busy_tag 6 +#define wippersnapper_display_v1_TftConfig_width_tag 1 +#define wippersnapper_display_v1_TftConfig_height_tag 2 +#define wippersnapper_display_v1_TftConfig_rotation_tag 3 +#define wippersnapper_display_v1_TftSpiConfig_bus_tag 1 +#define wippersnapper_display_v1_TftSpiConfig_pin_cs_tag 2 +#define wippersnapper_display_v1_TftSpiConfig_pin_dc_tag 3 +#define wippersnapper_display_v1_TftSpiConfig_pin_mosi_tag 4 +#define wippersnapper_display_v1_TftSpiConfig_pin_sck_tag 5 +#define wippersnapper_display_v1_TftSpiConfig_pin_rst_tag 6 +#define wippersnapper_display_v1_TftSpiConfig_pin_miso_tag 7 #define wippersnapper_display_v1_DisplayAddOrReplace_type_tag 1 #define wippersnapper_display_v1_DisplayAddOrReplace_name_tag 2 #define wippersnapper_display_v1_DisplayAddOrReplace_spi_epd_tag 3 -#define wippersnapper_display_v1_DisplayAddOrReplace_epd_config_tag 4 +#define wippersnapper_display_v1_DisplayAddOrReplace_spi_tft_tag 4 +#define wippersnapper_display_v1_DisplayAddOrReplace_config_epd_tag 5 +#define wippersnapper_display_v1_DisplayAddOrReplace_config_tft_tag 6 #define wippersnapper_display_v1_DisplayWrite_name_tag 1 #define wippersnapper_display_v1_DisplayWrite_message_tag 2 #define wippersnapper_display_v1_DisplayWrite_epd_options_tag 3 @@ -167,20 +184,41 @@ X(a, STATIC, SINGULAR, UENUM, mode, 1) #define wippersnapper_display_v1_EPDConfig_DEFAULT NULL #define wippersnapper_display_v1_EPDWriteOptions_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, INT32, text_size, 1) \ -X(a, STATIC, SINGULAR, UENUM, color, 2) +X(a, STATIC, SINGULAR, INT32, text_size, 1) #define wippersnapper_display_v1_EPDWriteOptions_CALLBACK NULL #define wippersnapper_display_v1_EPDWriteOptions_DEFAULT NULL +#define wippersnapper_display_v1_TftSpiConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, bus, 1) \ +X(a, STATIC, SINGULAR, STRING, pin_cs, 2) \ +X(a, STATIC, SINGULAR, STRING, pin_dc, 3) \ +X(a, STATIC, SINGULAR, STRING, pin_mosi, 4) \ +X(a, STATIC, SINGULAR, STRING, pin_sck, 5) \ +X(a, STATIC, SINGULAR, STRING, pin_rst, 6) \ +X(a, STATIC, SINGULAR, STRING, pin_miso, 7) +#define wippersnapper_display_v1_TftSpiConfig_CALLBACK NULL +#define wippersnapper_display_v1_TftSpiConfig_DEFAULT NULL + +#define wippersnapper_display_v1_TftConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, width, 1) \ +X(a, STATIC, SINGULAR, INT32, height, 2) \ +X(a, STATIC, SINGULAR, INT32, rotation, 3) +#define wippersnapper_display_v1_TftConfig_CALLBACK NULL +#define wippersnapper_display_v1_TftConfig_DEFAULT NULL + #define wippersnapper_display_v1_DisplayAddOrReplace_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, type, 1) \ X(a, STATIC, SINGULAR, STRING, name, 2) \ X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_epd,interface_type.spi_epd), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (config,epd_config,config.epd_config), 4) +X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_tft,interface_type.spi_tft), 4) \ +X(a, STATIC, ONEOF, MESSAGE, (config,config_epd,config.config_epd), 5) \ +X(a, STATIC, ONEOF, MESSAGE, (config,config_tft,config.config_tft), 6) #define wippersnapper_display_v1_DisplayAddOrReplace_CALLBACK NULL #define wippersnapper_display_v1_DisplayAddOrReplace_DEFAULT NULL #define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_spi_epd_MSGTYPE wippersnapper_display_v1_EpdSpiConfig -#define wippersnapper_display_v1_DisplayAddOrReplace_config_epd_config_MSGTYPE wippersnapper_display_v1_EPDConfig +#define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_spi_tft_MSGTYPE wippersnapper_display_v1_TftSpiConfig +#define wippersnapper_display_v1_DisplayAddOrReplace_config_config_epd_MSGTYPE wippersnapper_display_v1_EPDConfig +#define wippersnapper_display_v1_DisplayAddOrReplace_config_config_tft_MSGTYPE wippersnapper_display_v1_TftConfig #define wippersnapper_display_v1_DisplayRemove_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, name, 1) @@ -210,6 +248,8 @@ X(a, STATIC, SINGULAR, BOOL, did_remove, 2) extern const pb_msgdesc_t wippersnapper_display_v1_EpdSpiConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_EPDConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_EPDWriteOptions_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_TftSpiConfig_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_TftConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayAddOrReplace_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemove_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayWrite_msg; @@ -220,6 +260,8 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; #define wippersnapper_display_v1_EpdSpiConfig_fields &wippersnapper_display_v1_EpdSpiConfig_msg #define wippersnapper_display_v1_EPDConfig_fields &wippersnapper_display_v1_EPDConfig_msg #define wippersnapper_display_v1_EPDWriteOptions_fields &wippersnapper_display_v1_EPDWriteOptions_msg +#define wippersnapper_display_v1_TftSpiConfig_fields &wippersnapper_display_v1_TftSpiConfig_msg +#define wippersnapper_display_v1_TftConfig_fields &wippersnapper_display_v1_TftConfig_msg #define wippersnapper_display_v1_DisplayAddOrReplace_fields &wippersnapper_display_v1_DisplayAddOrReplace_msg #define wippersnapper_display_v1_DisplayRemove_fields &wippersnapper_display_v1_DisplayRemove_msg #define wippersnapper_display_v1_DisplayWrite_fields &wippersnapper_display_v1_DisplayWrite_msg @@ -229,10 +271,12 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; /* Maximum encoded size of messages (where known) */ #define wippersnapper_display_v1_EpdSpiConfig_size 46 #define wippersnapper_display_v1_EPDConfig_size 2 -#define wippersnapper_display_v1_EPDWriteOptions_size 13 -#define wippersnapper_display_v1_DisplayAddOrReplace_size 119 +#define wippersnapper_display_v1_EPDWriteOptions_size 11 +#define wippersnapper_display_v1_TftSpiConfig_size 53 +#define wippersnapper_display_v1_TftConfig_size 33 +#define wippersnapper_display_v1_DisplayAddOrReplace_size 157 #define wippersnapper_display_v1_DisplayRemove_size 65 -#define wippersnapper_display_v1_DisplayWrite_size 1106 +#define wippersnapper_display_v1_DisplayWrite_size 1104 #define wippersnapper_display_v1_DisplayAddedorReplaced_size 67 #define wippersnapper_display_v1_DisplayRemoved_size 67 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index 2033a041d..e383b7da0 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index ba86dbb96..2bdcf47c5 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index 80c5b8c7e..c627f5e5d 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index b2718e279..7a2737c99 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 11ba4661a..8ed127261 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index 28b37e0bb..b74fe6894 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index cc1697451..75346369d 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index 8bb1815f4..a6d53da4c 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index 2cf59f201..42aff48da 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index 12713219f..f48731f50 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index bc08aa6ba..c2899ddd6 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index b9b62fe13..d1ef554d0 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index 67dc1ade0..77a3f99c7 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 77f6843a2..d94e3f6e7 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED @@ -463,7 +463,7 @@ union wippersnapper_signal_v1_CreateSignalRequest_payload_size_union {char f6[(6 #define wippersnapper_signal_v1_SignalResponse_size 2 #define wippersnapper_signal_v1_PWMRequest_size 82 #define wippersnapper_signal_v1_PWMResponse_size 11 -#define wippersnapper_signal_v1_DisplayRequest_size 1109 +#define wippersnapper_signal_v1_DisplayRequest_size 1107 #define wippersnapper_signal_v1_DisplayResponse_size 69 #ifdef __cplusplus diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index 27928dd4f..0e7e19ca7 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index 867abee65..e7f5e92b4 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Aug 20 17:46:06 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From bf68aed49c8b15eebb5242d7f2f44470bf41598e Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 25 Aug 2025 11:32:34 -0400 Subject: [PATCH 25/76] Update for PB --- src/components/display/controller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 476e898fd..cb1d8cd47 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -49,8 +49,8 @@ bool DisplayController::Handle_Display_AddOrReplace( // Attempt to initialize display hardware instance bool did_begin = false; if (msgAdd->which_config == - wippersnapper_display_v1_DisplayAddOrReplace_epd_config_tag) { - did_begin = display->beginEPD(&msgAdd->config.epd_config, + wippersnapper_display_v1_DisplayAddOrReplace_config_epd_tag) { + did_begin = display->beginEPD(&msgAdd->config.config_epd, &msgAdd->interface_type.spi_epd); } else { WS_DEBUG_PRINTLN("[display] Unsupported display configuration type!"); From 6d5f95132b79c4220d108b8d252476d39cfbf2d6 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 25 Aug 2025 11:40:50 -0400 Subject: [PATCH 26/76] Update to match fbc883c..b7e6d06 --- src/components/display/controller.cpp | 2 ++ src/components/display/hardware.cpp | 15 ++++++++++++++- src/components/display/hardware.h | 2 ++ src/wippersnapper/description/v1/description.pb.c | 2 +- src/wippersnapper/description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 2 +- src/wippersnapper/display/v1/display.pb.h | 9 +++++---- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 2 +- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 23 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index cb1d8cd47..2d4545416 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -52,6 +52,8 @@ bool DisplayController::Handle_Display_AddOrReplace( wippersnapper_display_v1_DisplayAddOrReplace_config_epd_tag) { did_begin = display->beginEPD(&msgAdd->config.config_epd, &msgAdd->interface_type.spi_epd); + } else if (msgAdd->which_config == wippersnapper_display_v1_DisplayAddOrReplace_config_tft_tag) { + did_begin = display->beginTft(&msgAdd->config.config_tft, &msgAdd->interface_type.spi_tft); } else { WS_DEBUG_PRINTLN("[display] Unsupported display configuration type!"); return false; diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 13f8248da..1f2419cd8 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -199,7 +199,20 @@ bool DisplayHardware::beginEPD( return false; } - return true; // Configuration successful + return true; +} + +/*! + @brief Attempts to configure and initialize a TFT display + @param config + Pointer to the TFT configuration structure. + @param spi_config + Pointer to the SPI configuration structure for TFT. + @return True if configuration was successful, False otherwise. +*/ +bool beginTft(wippersnapper_display_v1_TftConfig *config, wippersnapper_display_v1_TftSpiConfig *spi_config) { + // TODO +return false; } /*! diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index f8f5dad61..087a8e2a5 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -40,6 +40,8 @@ class DisplayHardware { wippersnapper_display_v1_DisplayType getType(); bool beginEPD(wippersnapper_display_v1_EPDConfig *config, wippersnapper_display_v1_EpdSpiConfig *spi_config); + bool beginTft(wippersnapper_display_v1_TftConfig *config, + wippersnapper_display_v1_TftSpiConfig *spi_config); // // API for Adafruit_GFX that abstracts hardware functionality diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index d9c9db34a..8d8cb3aea 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index f931c6f89..d09c6efb8 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index b056ffec4..39fe9aca8 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index 2ab870c13..1c31c7661 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -15,7 +15,8 @@ typedef enum _wippersnapper_display_v1_DisplayType { wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_UNSPECIFIED = 0, wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_OLED = 1, - wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_EPD = 2 + wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_EPD = 2, + wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_TFT = 3 } wippersnapper_display_v1_DisplayType; typedef enum _wippersnapper_display_v1_EPDMode { @@ -99,8 +100,8 @@ typedef struct _wippersnapper_display_v1_DisplayWrite { /* Helper constants for enums */ #define _wippersnapper_display_v1_DisplayType_MIN wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_UNSPECIFIED -#define _wippersnapper_display_v1_DisplayType_MAX wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_EPD -#define _wippersnapper_display_v1_DisplayType_ARRAYSIZE ((wippersnapper_display_v1_DisplayType)(wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_EPD+1)) +#define _wippersnapper_display_v1_DisplayType_MAX wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_TFT +#define _wippersnapper_display_v1_DisplayType_ARRAYSIZE ((wippersnapper_display_v1_DisplayType)(wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_TFT+1)) #define _wippersnapper_display_v1_EPDMode_MIN wippersnapper_display_v1_EPDMode_EPD_MODE_UNSPECIFIED #define _wippersnapper_display_v1_EPDMode_MAX wippersnapper_display_v1_EPDMode_EPD_MODE_MONO diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index e383b7da0..2b844940b 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index 2bdcf47c5..84a16a5de 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index c627f5e5d..9a2cd926d 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 7a2737c99..0afda161c 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 8ed127261..87af9a92e 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index b74fe6894..3c9d51238 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index 75346369d..a7fb45322 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index a6d53da4c..65c3de75a 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index 42aff48da..7cfdd2901 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index f48731f50..e3cdf3439 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index c2899ddd6..7431b6661 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index d1ef554d0..063a04554 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index 77a3f99c7..ac1d37b30 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index d94e3f6e7..1939d6407 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index 0e7e19ca7..2f7925a88 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index e7f5e92b4..101d5bb60 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 14:48:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From 41598d93eeee1d450f8adef1c47c35cf0233f1cf Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 25 Aug 2025 12:15:17 -0400 Subject: [PATCH 27/76] Cleanup and share parsePin between beginTft and beginEpd --- src/components/display/hardware.cpp | 75 ++++++++++++++++++++--------- src/components/display/hardware.h | 1 + 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 1f2419cd8..15df6f99b 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -99,6 +99,21 @@ wippersnapper_display_v1_DisplayType DisplayHardware::getType() { return _type; } +/*! + @brief Parses a pin string (e.g., "D5") and returns the corresponding pin + number. + @param pinStr + The pin string to parse. + @return The pin number, or -1 if the string is invalid. +*/ +int16_t DisplayHardware::parsePin(const char* pinStr) { + if (!pinStr || strlen(pinStr) < 2 || pinStr[0] != 'D') { + return -1; + } + return atoi(pinStr + 1); +} + + /*! @brief Configures the EPD display with the provided configuration. @param config @@ -129,33 +144,18 @@ bool DisplayHardware::beginEPD( _drvDisp = nullptr; } - // Parse all SPI bus pins - // Check length - if (strlen(spi_config->pin_dc) < 2 || strlen(spi_config->pin_rst) < 2 || - strlen(spi_config->pin_cs) < 2) { - WS_DEBUG_PRINTLN("[display] Invalid SPI pin len!"); - return false; - } - // SPI pins must start with 'D' - if (spi_config->pin_dc[0] != 'D' || spi_config->pin_rst[0] != 'D' || - spi_config->pin_cs[0] != 'D') { - WS_DEBUG_PRINTLN("[display] SPI pins must start with 'D'!"); - return false; - } - // Parse and assign pins int16_t srcs = -1, busy = -1; - int16_t dc = (int16_t)atoi(spi_config->pin_dc + 1); - int16_t rst = (int16_t)atoi(spi_config->pin_rst + 1); - int16_t cs = (int16_t)atoi(spi_config->pin_cs + 1); + int16_t dc = parsePin(spi_config->pin_dc); + int16_t rst = parsePin(spi_config->pin_rst); + int16_t cs = parsePin(spi_config->pin_cs); // Optionally parse SRAM CS and BUSY pins - if (strlen(spi_config->pin_sram_cs) >= 2 && - spi_config->pin_sram_cs[0] == 'D') { - srcs = (int16_t)atoi(spi_config->pin_sram_cs + 1); + if (strlen(spi_config->pin_sram_cs) >= 2) { + srcs = parsePin(spi_config->pin_sram_cs); } - if (strlen(spi_config->pin_busy) >= 2 && spi_config->pin_busy[0] == 'D') { - busy = (int16_t)atoi(spi_config->pin_busy + 1); + if (strlen(spi_config->pin_busy) >= 2) { + busy = parsePin(spi_config->pin_busy); } // Configure SPI bus @@ -210,8 +210,35 @@ bool DisplayHardware::beginEPD( Pointer to the SPI configuration structure for TFT. @return True if configuration was successful, False otherwise. */ -bool beginTft(wippersnapper_display_v1_TftConfig *config, wippersnapper_display_v1_TftSpiConfig *spi_config) { - // TODO +bool DisplayHardware::beginTft(wippersnapper_display_v1_TftConfig *config, wippersnapper_display_v1_TftSpiConfig *spi_config) { + // Validate pointers + if (config == nullptr || spi_config == nullptr) { + WS_DEBUG_PRINTLN("[display] EPD config or SPI config is null!"); + return false; + } + + // If we already have a display driver assigned to this hardware instance, + // clean it up! + if (_drvDisp) { + delete _drvDisp; + _drvDisp = nullptr; + } + + // Parse and assign pins + int16_t rst = -1, miso = -1; + int16_t cs = parsePin(spi_config->pin_dc); + int16_t dc = parsePin(spi_config->pin_rst); + int16_t mosi = parsePin(spi_config->pin_cs); + int16_t sck = parsePin(spi_config->pin_sck); + + // Optionally parse SRAM CS and BUSY pins + if (strlen(spi_config->pin_rst) >= 2) { + rst = parsePin(spi_config->pin_rst); + } + if (strlen(spi_config->pin_miso) >= 2) { + miso = parsePin(spi_config->pin_miso); + } + return false; } diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 087a8e2a5..adac4a2a3 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -51,6 +51,7 @@ class DisplayHardware { void writeMessage(const char *message); private: + int16_t parsePin(const char* pinStr); bool detect_ssd1680(uint8_t cs, uint8_t dc, uint8_t rst); char _name[64]; ///< Identifies the hardware instance wippersnapper_display_v1_DisplayType _type; ///< Display type From 5c42673c032116e4ababf464bdfbd28b95593df6 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 25 Aug 2025 15:21:30 -0400 Subject: [PATCH 28/76] Pull in ST7789 --- platformio.ini | 2 +- src/components/display/drivers/dispDrvBase.h | 23 +++ .../display/drivers/dispDrvSt7789.h | 138 ++++++++++++++++++ src/components/display/hardware.cpp | 73 ++++++--- src/components/display/hardware.h | 3 +- 5 files changed, 220 insertions(+), 19 deletions(-) create mode 100644 src/components/display/drivers/dispDrvSt7789.h diff --git a/platformio.ini b/platformio.ini index 904558804..1bbf6019d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -212,7 +212,7 @@ extra_scripts = pre:rename_usb_config.py extends = common:esp32 board = adafruit_feather_esp32s2_tft build_flags = -DARDUINO_ADAFRUIT_FEATHER_ESP32S2_TFT -DBOARD_HAS_PSRAM -board_build.partitions = tinyuf2-partitions-4MB.csv +board_build.partitions = tinyuf2-partitions-4MB-noota.csv extra_scripts = pre:rename_usb_config.py ; Adafruit Feather ESP32-S2 Reverse TFT diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index c7d624836..45b177e31 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -43,6 +43,26 @@ class dispDrvBase { : _pin_dc(dc), _pin_rst(rst), _pin_cs(cs), _pin_sram_cs(sram_cs), _pin_busy(busy) {} + /*! + @brief Constructor for the base display driver for SPI TFT displays. + @param cs + Chip Select pin for the display. + @param dc + Data/Command pin for the display. + @param mosi + MOSI pin for the display. + @param sck + SCK pin for the display. + @param rst + Optional Reset pin for the display. + @param miso + Optional MISO pin for the display. + */ + dispDrvBase(int8_t cs, int8_t dc, int8_t mosi, int8_t sck, int8_t rst = -1, + int8_t miso = -1) + : _pin_cs(cs), _pin_dc(dc), _pin_mosi(mosi), _pin_sck(sck), _pin_rst(rst), + _pin_miso(miso) {} + /*! @brief Destructor for the base display driver. This destructor is virtual to allow derived classes to clean up @@ -74,6 +94,9 @@ class dispDrvBase { int16_t _pin_cs; ///< Chip Select pin int16_t _pin_busy; ///< Optional Busy pin int16_t _pin_sram_cs; ///< Optional EPD SRAM chip select pin + uint16_t _pin_mosi; ///< Optional MOSI pin for SPI TFT displays + uint16_t _pin_miso; ///< Optional MISO pin for SPI TFT displays + uint16_t _pin_sck; ///< Optional SCK pin for SPI TFT displays uint8_t _text_sz = 1; ///< Text size for displaying a message int16_t _height; ///< Height of the display int16_t _width; ///< Width of the display diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h new file mode 100644 index 000000000..41c0c757e --- /dev/null +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -0,0 +1,138 @@ +/*! + * @file src/components/display/drivers/dispDrvSt7789.h + * + * Driver for ST7789-based TFT displays. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DISP_DRV_ST7789 +#define WS_DISP_DRV_ST7789 + +#include "dispDrvBase.h" +#include + +/*! + @brief Driver for ST7789-based TFT displays. +*/ +class dispDrvSt7789 : public dispDrvBase { +public: + /*! + @brief Constructor for the ST7789 display driver. + @param cs + Chip Select pin for the display. + @param dc + Data/Command pin for the display. + @param mosi + MOSI pin for the display. + @param sck + SCK pin for the display. + @param rst + Optional Reset pin for the display. + @param miso + Optional MISO pin for the display. + */ + dispDrvSt7789(int16_t cs, int16_t dc, int16_t mosi, int16_t sck, + int16_t rst = -1, int16_t miso = -1) + : dispDrvBase(cs, dc, mosi, sck, rst, miso), _display(nullptr) {} + + ~dispDrvSt7789() { + if (_display) { + delete _display; + _display = nullptr; + } + } + + /*! + @brief Attempts to initialize the ST7789 TFT driver. + @return True if the display was initialized successfully, false otherwise. + */ + bool begin() override { + +// Special configuration for Feather TFTs +#if defined(TFT_BACKLITE) + // turn on backlite + pinMode(TFT_BACKLITE, OUTPUT); + digitalWrite(TFT_BACKLITE, HIGH); + + // turn on the TFT / I2C power supply + pinMode(TFT_I2C_POWER, OUTPUT); + digitalWrite(TFT_I2C_POWER, HIGH); + delay(10); +#endif + + _display = new Adafruit_ST7789(_pin_cs, _pin_dc, _pin_rst); + + if (!_display) + return false; + + _display->init(_width, _height); + _display->setRotation(_rotation); + _display->fillScreen(ST77XX_BLACK); + _display->setTextColor(ST77XX_WHITE); + return true; + } + + /*! + @brief Writes a message to the display. + @param message + The message to write to the display. + @note This method overrides the base class method to provide specific + functionality for the Think Ink Grayscale 4 EAAMGFGN driver. + */ + virtual void writeMessage(const char *message) override { + if (_display == nullptr) + return; + + // Start with a fresh display buffer + _display->fillScreen(ST77XX_BLACK); + int16_t y_idx = 0; + _display->setCursor(0, y_idx); + + // Calculate the line height based on the text size (NOTE: base height is + // 8px) + int16_t line_height = 8 * _text_sz; + uint16_t c_idx = 0; + size_t msg_size = strlen(message); + for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) { + if (y_idx + line_height > _height) + break; + if (message[i] == '\\' && i + 1 < msg_size && + (message[i + 1] == 'n' || message[i + 1] == 'r')) { + // Handle \r\n sequence as a single newline + if (message[i + 1] == 'r' && i + 3 < msg_size && + message[i + 2] == '\\' && message[i + 3] == 'n') { + // Skip to the next line + if (y_idx + line_height > _height) + break; + y_idx += line_height; + _display->setCursor(0, y_idx); + i += 3; + } else if (message[i + 1] == 'n') { + // Skip to the next line + if (y_idx + line_height > _height) + break; + y_idx += line_height; + _display->setCursor(0, y_idx); + i++; + } + } else if (message[i] == 0xC2 && message[i + 1] == 0xB0) { + _display->write(char(248)); + i++; + } else { + _display->print(message[i]); + } + } + } + +private: + Adafruit_ST7789 *_display; +}; + +#endif // WS_DISP_DRV_ST7789 \ No newline at end of file diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 15df6f99b..6052700ad 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -17,12 +17,12 @@ /*! @brief Lambda function to create a dispDrvBase instance */ -using FnCreateDispDrv = +using FnCreateDispDrvEpd = std::function; // Factory for creating a new display drivers // NOTE: When you add a new display driver, make sure to add it to the factory! -static const std::map FactoryDrvDisp = { +static const std::map FactoryDrvDispEpd = { {"thinkink-gs4-eaamfgn", [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, int16_t busy) -> dispDrvBase * { @@ -35,7 +35,29 @@ static const std::map FactoryDrvDisp = { }}}; /*! - @brief Creates a new display driver instance based on the driver name. + @brief Lambda function to create a dispDrvBase SPI TFT instance +*/ +using FnCreateDispDrvTft = std::function; + +// Factory for creating a new SPI TFT display driver +// NOTE: When you add a new SPI TFT display driver, make sure to add it to the +// factory! +static const std::map FactoryDrvDispTft = { + {"st7735", + [](int16_t cs, int16_t dc, int16_t mosi, int16_t sck, int16_t rst, + int16_t miso) -> dispDrvBase * { + return new dispDrvSt7789(cs, dc, mosi, sck, rst, miso); + }}, + {"st7789", + [](int16_t cs, int16_t dc, int16_t mosi, int16_t sck, int16_t rst, + int16_t miso) -> dispDrvBase * { + return new dispDrvSt7789(cs, dc, mosi, sck, rst, miso); + }}}; + +/*! + @brief Creates a new E-Ink display driver instance based on the driver + name. @param driver_name The name of the display driver to create. @param dc @@ -51,16 +73,32 @@ static const std::map FactoryDrvDisp = { @return Pointer to the created display driver instance, or nullptr if the driver name is not recognized. */ -dispDrvBase *CreateDrvDisp(const char *driver_name, int16_t dc, int16_t rst, - int16_t cs, int16_t sram_cs = -1, - int16_t busy = -1) { - auto it = FactoryDrvDisp.find(driver_name); - if (it == FactoryDrvDisp.end()) +dispDrvBase *CreateDrvDispEpd(const char *driver_name, int16_t dc, int16_t rst, + int16_t cs, int16_t sram_cs = -1, + int16_t busy = -1) { + auto it = FactoryDrvDispEpd.find(driver_name); + if (it == FactoryDrvDispEpd.end()) return nullptr; return it->second(dc, rst, cs, sram_cs, busy); } +/*! + @brief Creates a new SPI TFT display driver instance based on the driver + name. + @param driver_name + The name of the SPI TFT display driver to create. +*/ +dispDrvBase *CreateDrvDispTft(const char *driver_name, int16_t cs, int16_t dc, + int16_t mosi, int16_t sck, int16_t rst = -1, + int16_t miso = -1) { + auto it = FactoryDrvDispTft.find(driver_name); + if (it == FactoryDrvDispTft.end()) + return nullptr; + + return it->second(cs, dc, mosi, sck, rst, miso); +} + /*! @brief Constructs a new DisplayHardware object @param name @@ -106,14 +144,13 @@ wippersnapper_display_v1_DisplayType DisplayHardware::getType() { The pin string to parse. @return The pin number, or -1 if the string is invalid. */ -int16_t DisplayHardware::parsePin(const char* pinStr) { - if (!pinStr || strlen(pinStr) < 2 || pinStr[0] != 'D') { - return -1; - } - return atoi(pinStr + 1); +int16_t DisplayHardware::parsePin(const char *pinStr) { + if (!pinStr || strlen(pinStr) < 2 || pinStr[0] != 'D') { + return -1; + } + return atoi(pinStr + 1); } - /*! @brief Configures the EPD display with the provided configuration. @param config @@ -179,7 +216,7 @@ bool DisplayHardware::beginEPD( } // Create display driver object using the factory function - _drvDisp = CreateDrvDisp(_name, dc, rst, cs, srcs, busy); + _drvDisp = CreateDrvDispEpd(_name, dc, rst, cs, srcs, busy); if (!_drvDisp) { WS_DEBUG_PRINTLN("[display] Failed to create display driver!"); return false; // Failed to create display driver @@ -210,7 +247,9 @@ bool DisplayHardware::beginEPD( Pointer to the SPI configuration structure for TFT. @return True if configuration was successful, False otherwise. */ -bool DisplayHardware::beginTft(wippersnapper_display_v1_TftConfig *config, wippersnapper_display_v1_TftSpiConfig *spi_config) { +bool DisplayHardware::beginTft( + wippersnapper_display_v1_TftConfig *config, + wippersnapper_display_v1_TftSpiConfig *spi_config) { // Validate pointers if (config == nullptr || spi_config == nullptr) { WS_DEBUG_PRINTLN("[display] EPD config or SPI config is null!"); @@ -239,7 +278,7 @@ bool DisplayHardware::beginTft(wippersnapper_display_v1_TftConfig *config, wippe miso = parsePin(spi_config->pin_miso); } -return false; + return false; } /*! diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index adac4a2a3..edfac6780 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -16,6 +16,7 @@ #define WS_DISPLAY_HARDWARE_H #include "Wippersnapper.h" #include "drivers/dispDrvBase.h" +#include "drivers/dispDrvSt7789.h" #include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h" #include "drivers/dispDrvThinkInkGrayscale4T5.h" #include @@ -51,7 +52,7 @@ class DisplayHardware { void writeMessage(const char *message); private: - int16_t parsePin(const char* pinStr); + int16_t parsePin(const char *pinStr); bool detect_ssd1680(uint8_t cs, uint8_t dc, uint8_t rst); char _name[64]; ///< Identifies the hardware instance wippersnapper_display_v1_DisplayType _type; ///< Display type From 6c1666efd49026e152e0eae87da5931ca91d5923 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 25 Aug 2025 15:25:01 -0400 Subject: [PATCH 29/76] Expose more funcs in drvBase --- src/Wippersnapper_demo.ino.cpp | 26 ++++++++++++++++++++ src/components/display/drivers/dispDrvBase.h | 11 +++++++++ src/components/display/hardware.cpp | 15 ++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp new file mode 100644 index 000000000..9dd1009c0 --- /dev/null +++ b/src/Wippersnapper_demo.ino.cpp @@ -0,0 +1,26 @@ +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpdpm_2l97" +#include +# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +#include "Wippersnapper_Networking.h" +Wippersnapper_WiFi wipper; + + +#define WS_DEBUG +void setup(); +void loop(); +#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +void setup() { + + wipper.provision(); + + Serial.begin(115200); + + + wipper.connect(); + +} + +void loop() { + wipper.run(); +} \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index 45b177e31..fdcbad7db 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -80,6 +80,12 @@ class dispDrvBase { */ virtual bool begin(thinkinkmode_t mode, bool reset = true); + /*! + @brief Attempts to initialize a SPI TFT driver. + @return True if the display was initialized successfully, false otherwise. + */ + virtual bool begin(); + /*! @brief Writes a message to the display. @param message @@ -88,6 +94,10 @@ class dispDrvBase { */ virtual void writeMessage(const char *message) = 0; + void setWidth(int16_t w) { _width = w; } + void setHeight(int16_t h) { _height = h; } + void setRotation(uint8_t r) { _rotation = r; } + protected: int16_t _pin_dc; ///< Data/Command pin int16_t _pin_rst; ///< Reset pin @@ -100,6 +110,7 @@ class dispDrvBase { uint8_t _text_sz = 1; ///< Text size for displaying a message int16_t _height; ///< Height of the display int16_t _width; ///< Width of the display + uint8_t _rotation; ///< Rotation of the display }; #endif // WS_DISP_DRV_BASE_H \ No newline at end of file diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 6052700ad..6501b7ead 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -278,7 +278,20 @@ bool DisplayHardware::beginTft( miso = parsePin(spi_config->pin_miso); } - return false; + // Create display driver object using the factory function + _drvDisp = CreateDrvDispTft(_name, cs, dc, mosi, sck, rst, miso); + if (!_drvDisp) { + WS_DEBUG_PRINTLN("[display] Failed to create display driver!"); + return false; + } + + _drvDisp->setWidth(config->width); + _drvDisp->setHeight(config->height); + _drvDisp->setRotation(config->rotation); + _drvDisp->begin(); + + WS_DEBUG_PRINTLN("[display] TFT display initialized successfully!"); + return true; } /*! From 33e43d56806eaa110c648107cf9e375700c8f681 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 25 Aug 2025 15:28:11 -0400 Subject: [PATCH 30/76] fix linker complaint --- src/Wippersnapper_demo.ino.cpp | 26 -------------------- src/components/display/drivers/dispDrvBase.h | 4 +-- 2 files changed, 2 insertions(+), 28 deletions(-) delete mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp deleted file mode 100644 index 9dd1009c0..000000000 --- a/src/Wippersnapper_demo.ino.cpp +++ /dev/null @@ -1,26 +0,0 @@ -# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpdpm_2l97" -#include -# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -#include "Wippersnapper_Networking.h" -Wippersnapper_WiFi wipper; - - -#define WS_DEBUG -void setup(); -void loop(); -#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -void setup() { - - wipper.provision(); - - Serial.begin(115200); - - - wipper.connect(); - -} - -void loop() { - wipper.run(); -} \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index fdcbad7db..ddb53c52f 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -78,13 +78,13 @@ class dispDrvBase { Whether to reset the display before initialization. @return True if the display was initialized successfully, false otherwise. */ - virtual bool begin(thinkinkmode_t mode, bool reset = true); + virtual bool begin(thinkinkmode_t mode, bool reset = true) { return false; } /*! @brief Attempts to initialize a SPI TFT driver. @return True if the display was initialized successfully, false otherwise. */ - virtual bool begin(); + virtual bool begin() { return false; } /*! @brief Writes a message to the display. From 098edaa9ba28b9d9f4e71d5709ce83f22b0611b7 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 25 Aug 2025 16:03:30 -0400 Subject: [PATCH 31/76] Fix text size, DisplayWrite not showing up yet --- src/components/display/drivers/dispDrvSt7789.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index 41c0c757e..ea1f064a7 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -76,6 +76,7 @@ class dispDrvSt7789 : public dispDrvBase { _display->setRotation(_rotation); _display->fillScreen(ST77XX_BLACK); _display->setTextColor(ST77XX_WHITE); + _display->setTextSize(_text_sz); return true; } From 437b0915ed0c485dba24475b2f630a16dfcc9a03 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 26 Aug 2025 11:24:54 -0400 Subject: [PATCH 32/76] Fix init for ST7789 --- src/Wippersnapper_demo.ino.cpp | 26 +++++++++++++++++++ .../display/drivers/dispDrvSt7789.h | 3 +++ src/components/display/hardware.cpp | 7 +++-- 3 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp new file mode 100644 index 000000000..d9388162e --- /dev/null +++ b/src/Wippersnapper_demo.ino.cpp @@ -0,0 +1,26 @@ +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmp856663z2" +#include +# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +#include "Wippersnapper_Networking.h" +Wippersnapper_WiFi wipper; + + +#define WS_DEBUG +void setup(); +void loop(); +#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +void setup() { + + wipper.provision(); + + Serial.begin(115200); + + + wipper.connect(); + +} + +void loop() { + wipper.run(); +} \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index ea1f064a7..73e233524 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -73,10 +73,13 @@ class dispDrvSt7789 : public dispDrvBase { return false; _display->init(_width, _height); + _display->setRotation(_rotation); _display->fillScreen(ST77XX_BLACK); _display->setTextColor(ST77XX_WHITE); _display->setTextSize(_text_sz); + _display->setCursor(0, 0); + _display->println("Display Init"); return true; } diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 6501b7ead..71fb03484 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -263,11 +263,10 @@ bool DisplayHardware::beginTft( _drvDisp = nullptr; } - // Parse and assign pins int16_t rst = -1, miso = -1; - int16_t cs = parsePin(spi_config->pin_dc); - int16_t dc = parsePin(spi_config->pin_rst); - int16_t mosi = parsePin(spi_config->pin_cs); + int16_t cs = parsePin(spi_config->pin_cs); + int16_t dc = parsePin(spi_config->pin_dc); + int16_t mosi = parsePin(spi_config->pin_mosi); int16_t sck = parsePin(spi_config->pin_sck); // Optionally parse SRAM CS and BUSY pins From 7be4cadfd01bfd4222e2cf81fb5fefcf39eef027 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 26 Aug 2025 12:12:21 -0400 Subject: [PATCH 33/76] Set text size via new setter --- src/Wippersnapper_demo.ino.cpp | 2 +- src/components/display/drivers/dispDrvBase.h | 2 ++ src/components/display/drivers/dispDrvSt7789.h | 12 ++++++++---- src/components/display/hardware.cpp | 10 ++++++++++ 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp index d9388162e..0c06bef48 100644 --- a/src/Wippersnapper_demo.ino.cpp +++ b/src/Wippersnapper_demo.ino.cpp @@ -1,4 +1,4 @@ -# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmp856663z2" +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpr2yz0h9_" #include # 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" # 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index ddb53c52f..ff4f127fa 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -98,6 +98,8 @@ class dispDrvBase { void setHeight(int16_t h) { _height = h; } void setRotation(uint8_t r) { _rotation = r; } + virtual void setTextSize(uint8_t s) { _text_sz = s; } + protected: int16_t _pin_dc; ///< Data/Command pin int16_t _pin_rst; ///< Reset pin diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index 73e233524..254eb89f4 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -18,6 +18,8 @@ #include "dispDrvBase.h" #include +#define ST7789_TEXT_SZ_DEFAULT 2 + /*! @brief Driver for ST7789-based TFT displays. */ @@ -73,16 +75,18 @@ class dispDrvSt7789 : public dispDrvBase { return false; _display->init(_width, _height); - _display->setRotation(_rotation); _display->fillScreen(ST77XX_BLACK); _display->setTextColor(ST77XX_WHITE); - _display->setTextSize(_text_sz); - _display->setCursor(0, 0); - _display->println("Display Init"); + _display->setTextSize(ST7789_TEXT_SZ_DEFAULT); return true; } + void setTextSize(uint8_t s) override { + _text_sz = s; + _display->setTextSize(s); + } + /*! @brief Writes a message to the display. @param message diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 71fb03484..300df0ded 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -50,6 +50,11 @@ static const std::map FactoryDrvDispTft = { return new dispDrvSt7789(cs, dc, mosi, sck, rst, miso); }}, {"st7789", + [](int16_t cs, int16_t dc, int16_t mosi, int16_t sck, int16_t rst, + int16_t miso) -> dispDrvBase * { + return new dispDrvSt7789(cs, dc, mosi, sck, rst, miso); + }}, + {"st7789-large", [](int16_t cs, int16_t dc, int16_t mosi, int16_t sck, int16_t rst, int16_t miso) -> dispDrvBase * { return new dispDrvSt7789(cs, dc, mosi, sck, rst, miso); @@ -284,6 +289,11 @@ bool DisplayHardware::beginTft( return false; } + // Check if name has -large suffix, and if so, set a larger default text size + if (strstr(_name, "-large") != nullptr) { + _drvDisp->setTextSize(3); // Large text size for -large displays + } + _drvDisp->setWidth(config->width); _drvDisp->setHeight(config->height); _drvDisp->setRotation(config->rotation); From c8961599bf59ad4c77532c197679faf92cd65d7d Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 26 Aug 2025 15:32:57 -0400 Subject: [PATCH 34/76] Add Doxygen --- src/Wippersnapper_demo.ino.cpp | 26 ---------- src/components/display/drivers/dispDrvBase.h | 24 +++++++++ .../display/drivers/dispDrvSt7789.h | 16 ++++-- src/components/display/hardware.cpp | 52 +++++++++++++++---- src/components/display/hardware.h | 1 + 5 files changed, 78 insertions(+), 41 deletions(-) delete mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp deleted file mode 100644 index 0c06bef48..000000000 --- a/src/Wippersnapper_demo.ino.cpp +++ /dev/null @@ -1,26 +0,0 @@ -# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpr2yz0h9_" -#include -# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -#include "Wippersnapper_Networking.h" -Wippersnapper_WiFi wipper; - - -#define WS_DEBUG -void setup(); -void loop(); -#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -void setup() { - - wipper.provision(); - - Serial.begin(115200); - - - wipper.connect(); - -} - -void loop() { - wipper.run(); -} \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index ff4f127fa..d74c2d733 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -94,10 +94,34 @@ class dispDrvBase { */ virtual void writeMessage(const char *message) = 0; + /*! + @brief Sets the width of the display. + @param w + The width of the display in pixels. + */ void setWidth(int16_t w) { _width = w; } + + /*! + @brief Sets the height of the display. + @param h + The height of the display in pixels. + */ void setHeight(int16_t h) { _height = h; } + + /*! + @brief Sets the rotation of the display. + @param r + The rotation of the display (0-3). + */ void setRotation(uint8_t r) { _rotation = r; } + /*! + @brief Sets the text size for the display. + @param s + The text size to set. + @note This method can be overridden by derived classes to provide + specific functionality. + */ virtual void setTextSize(uint8_t s) { _text_sz = s; } protected: diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index 254eb89f4..d9c1b2c79 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -18,7 +18,7 @@ #include "dispDrvBase.h" #include -#define ST7789_TEXT_SZ_DEFAULT 2 +#define ST7789_TEXT_SZ_DEFAULT 2 ///< Default text size for ST7789 displays /*! @brief Driver for ST7789-based TFT displays. @@ -70,19 +70,27 @@ class dispDrvSt7789 : public dispDrvBase { #endif _display = new Adafruit_ST7789(_pin_cs, _pin_dc, _pin_rst); - if (!_display) return false; _display->init(_width, _height); _display->setRotation(_rotation); + setTextSize(ST7789_TEXT_SZ_DEFAULT); _display->fillScreen(ST77XX_BLACK); _display->setTextColor(ST77XX_WHITE); - _display->setTextSize(ST7789_TEXT_SZ_DEFAULT); return true; } + /*! + @brief Sets the text size for the display. + @param s + The text size to set. + @note This method overrides the base class method to provide specific + functionality for the ST7789 driver. + */ void setTextSize(uint8_t s) override { + if (!_display) + return; _text_sz = s; _display->setTextSize(s); } @@ -92,7 +100,7 @@ class dispDrvSt7789 : public dispDrvBase { @param message The message to write to the display. @note This method overrides the base class method to provide specific - functionality for the Think Ink Grayscale 4 EAAMGFGN driver. + functionality for the ST7789 driver. */ virtual void writeMessage(const char *message) override { if (_display == nullptr) diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 300df0ded..c4d7cfca0 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -50,11 +50,6 @@ static const std::map FactoryDrvDispTft = { return new dispDrvSt7789(cs, dc, mosi, sck, rst, miso); }}, {"st7789", - [](int16_t cs, int16_t dc, int16_t mosi, int16_t sck, int16_t rst, - int16_t miso) -> dispDrvBase * { - return new dispDrvSt7789(cs, dc, mosi, sck, rst, miso); - }}, - {"st7789-large", [](int16_t cs, int16_t dc, int16_t mosi, int16_t sck, int16_t rst, int16_t miso) -> dispDrvBase * { return new dispDrvSt7789(cs, dc, mosi, sck, rst, miso); @@ -93,6 +88,20 @@ dispDrvBase *CreateDrvDispEpd(const char *driver_name, int16_t dc, int16_t rst, name. @param driver_name The name of the SPI TFT display driver to create. + @param cs + Chip Select pin number. + @param dc + Data/Command pin number. + @param mosi + MOSI pin number. + @param sck + SCK pin number. + @param rst + Optional Reset pin number (default: -1). + @param miso + Optional MISO pin number (default: -1). + @return Pointer to the created display driver instance, or nullptr if the + driver name is not recognized. */ dispDrvBase *CreateDrvDispTft(const char *driver_name, int16_t cs, int16_t dc, int16_t mosi, int16_t sck, int16_t rst = -1, @@ -244,6 +253,18 @@ bool DisplayHardware::beginEPD( return true; } +/*! + @brief Removes a suffix from the hardware instance name, if it exists. + @param suffix + The suffix to remove (e.g., "-lg", "-md", "-sm"). +*/ +void DisplayHardware::removeSuffix(const char *suffix) { + char *suffix_pos = strstr(_name, suffix); + if (suffix_pos) { + *suffix_pos = '\0'; // Truncate string at suffix position + } +} + /*! @brief Attempts to configure and initialize a TFT display @param config @@ -282,6 +303,20 @@ bool DisplayHardware::beginTft( miso = parsePin(spi_config->pin_miso); } + // Configure text size based on suffix in driver name + uint8_t text_sz; // Default text size + if (strstr(_name, "-lg") != nullptr) { + // Larger text size for displays with -lg suffix + text_sz = 4; + removeSuffix("-lg"); + } else if (strstr(_name, "-md") != nullptr) { + // Larger text size for displays with -md suffix + text_sz = 3; + removeSuffix("-md"); + } else { + text_sz = 1; + } + // Create display driver object using the factory function _drvDisp = CreateDrvDispTft(_name, cs, dc, mosi, sck, rst, miso); if (!_drvDisp) { @@ -289,17 +324,12 @@ bool DisplayHardware::beginTft( return false; } - // Check if name has -large suffix, and if so, set a larger default text size - if (strstr(_name, "-large") != nullptr) { - _drvDisp->setTextSize(3); // Large text size for -large displays - } - _drvDisp->setWidth(config->width); _drvDisp->setHeight(config->height); _drvDisp->setRotation(config->rotation); _drvDisp->begin(); + _drvDisp->setTextSize(text_sz); - WS_DEBUG_PRINTLN("[display] TFT display initialized successfully!"); return true; } diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index edfac6780..9446f1467 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -53,6 +53,7 @@ class DisplayHardware { private: int16_t parsePin(const char *pinStr); + void removeSuffix(const char *suffix); bool detect_ssd1680(uint8_t cs, uint8_t dc, uint8_t rst); char _name[64]; ///< Identifies the hardware instance wippersnapper_display_v1_DisplayType _type; ///< Display type From 1c265a1ba93b9d14d72f8f6f5321e593da40190b Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 26 Aug 2025 16:53:23 -0400 Subject: [PATCH 35/76] Clang! --- src/components/display/controller.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 2d4545416..29123824e 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -52,8 +52,10 @@ bool DisplayController::Handle_Display_AddOrReplace( wippersnapper_display_v1_DisplayAddOrReplace_config_epd_tag) { did_begin = display->beginEPD(&msgAdd->config.config_epd, &msgAdd->interface_type.spi_epd); - } else if (msgAdd->which_config == wippersnapper_display_v1_DisplayAddOrReplace_config_tft_tag) { - did_begin = display->beginTft(&msgAdd->config.config_tft, &msgAdd->interface_type.spi_tft); + } else if (msgAdd->which_config == + wippersnapper_display_v1_DisplayAddOrReplace_config_tft_tag) { + did_begin = display->beginTft(&msgAdd->config.config_tft, + &msgAdd->interface_type.spi_tft); } else { WS_DEBUG_PRINTLN("[display] Unsupported display configuration type!"); return false; From 5efe8cee93fb2e47df063465e84d6986f885020d Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 27 Aug 2025 11:31:54 -0400 Subject: [PATCH 36/76] Address @tyeth review --- library.properties | 2 +- src/Wippersnapper.cpp | 3 --- src/components/display/controller.cpp | 1 + .../display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h | 1 + src/components/display/hardware.cpp | 2 +- src/components/register/Wippersnapper_Register.cpp | 1 - 6 files changed, 4 insertions(+), 6 deletions(-) diff --git a/library.properties b/library.properties index 5cf33a228..15a03319c 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper category=Communication url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino architectures=* -depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD +depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 8cf7c9b7d..3d0eea65f 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -3015,13 +3015,10 @@ void Wippersnapper::connect() { WS._ui_helper->build_scr_monitor(); #endif - WS.pinCfgCompleted = true; - // Initialize Digital IO class WS._digitalGPIO = new Wippersnapper_DigitalGPIO(20); // Initialize Analog IO class WS._analogIO = new Wippersnapper_AnalogIO(5, 3.3); - WS._boardStatus = WS_BOARD_DEF_OK; // Configure hardware while (!WS.pinCfgCompleted) { diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 29123824e..709ef8a4f 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -58,6 +58,7 @@ bool DisplayController::Handle_Display_AddOrReplace( &msgAdd->interface_type.spi_tft); } else { WS_DEBUG_PRINTLN("[display] Unsupported display configuration type!"); + delete display; return false; } diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index 6fcbb1cfe..426307d1b 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -123,6 +123,7 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { i++; } } else if (message[i] == 0xC2 && message[i + 1] == 0xB0) { + // Degree symbol _display->write(char(248)); i++; } else { diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index c4d7cfca0..798932f99 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -15,7 +15,7 @@ #include "controller.h" /*! - @brief Lambda function to create a dispDrvBase instance + @brief Lambda function to create a dispDrvBase EPD instance. */ using FnCreateDispDrvEpd = std::function; diff --git a/src/components/register/Wippersnapper_Register.cpp b/src/components/register/Wippersnapper_Register.cpp index 4ad9ec5c4..522818997 100644 --- a/src/components/register/Wippersnapper_Register.cpp +++ b/src/components/register/Wippersnapper_Register.cpp @@ -77,7 +77,6 @@ bool Wippersnapper::encodePubRegistrationReq() { /****************************************************************************/ void Wippersnapper::pollRegistrationResp() { // Blocking loop, WDT reset upon failure. - WS._boardStatus = WS_BOARD_DEF_OK; while (WS._boardStatus != WS_BOARD_DEF_OK) { WS_DEBUG_PRINT("Polling for registration message response..."); WS_DEBUG_PRINTLN(WS._boardStatus); From a4d9e8e318bfb26e99556e5e6e3dc0c133c5c791 Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 3 Sep 2025 13:14:25 -0400 Subject: [PATCH 37/76] Removing LVGL display/ in favor of components/display approach --- src/Wippersnapper.cpp | 195 ------- src/Wippersnapper.h | 15 - src/Wippersnapper_Boards.h | 1 - .../analogIO/Wippersnapper_AnalogIO.cpp | 5 - .../digitalIO/Wippersnapper_DigitalGPIO.cpp | 39 -- .../display/drivers/dispDrvSt7789.h | 5 +- src/components/ds18x20/ws_ds18x20.cpp | 23 - src/components/i2c/WipperSnapper_I2C.cpp | 3 - src/components/pixels/ws_pixels.cpp | 31 -- src/display/symbols/cloud_30px.c | 158 ------ src/display/symbols/errorTriangle.c | 492 ------------------ src/display/symbols/file.c | 144 ----- src/display/symbols/turtle_16.c | 124 ----- src/display/symbols/turtle_30px.c | 152 ------ src/display/symbols/wifi_30px.c | 157 ------ src/display/ws_display_driver.cpp | 143 ----- src/display/ws_display_driver.h | 56 -- src/display/ws_display_tooltips.h | 28 - src/display/ws_display_ui_helper.cpp | 472 ----------------- src/display/ws_display_ui_helper.h | 91 ---- src/provisioning/tinyusb/Wippersnapper_FS.cpp | 26 +- 21 files changed, 7 insertions(+), 2353 deletions(-) delete mode 100644 src/display/symbols/cloud_30px.c delete mode 100644 src/display/symbols/errorTriangle.c delete mode 100644 src/display/symbols/file.c delete mode 100644 src/display/symbols/turtle_16.c delete mode 100644 src/display/symbols/turtle_30px.c delete mode 100644 src/display/symbols/wifi_30px.c delete mode 100644 src/display/ws_display_driver.cpp delete mode 100644 src/display/ws_display_driver.h delete mode 100644 src/display/ws_display_tooltips.h delete mode 100644 src/display/ws_display_ui_helper.cpp delete mode 100644 src/display/ws_display_ui_helper.h diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 3d0eea65f..1c1e4f3c3 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -108,29 +108,6 @@ void Wippersnapper::provision() { _littleFS = new WipperSnapper_LittleFS(); #endif -#ifdef USE_DISPLAY - // Initialize the display - displayConfig config; - if (!WS._fileSystem->parseDisplayConfig(config)) { - WS._fileSystem->parseDisplayConfig(config, true); - } - WS._display = new ws_display_driver(config); - // Begin display - if (!WS._display->begin()) { - WS_DEBUG_PRINTLN("Unable to enable display driver and LVGL"); - haltError("Unable to enable display driver, please check the json " - "configuration!"); - } - - WS._display->enableLogging(); - releaseStatusLED(); // don't use status LED if we are using the display - // UI Setup - WS._ui_helper = new ws_display_ui_helper(WS._display); - WS._ui_helper->set_bg_black(); - WS._ui_helper->show_scr_load(); - WS._ui_helper->set_label_status("Validating Credentials..."); -#endif - // Parse secrets.json file #ifdef USE_TINYUSB _fileSystem->parseSecrets(); @@ -143,11 +120,6 @@ void Wippersnapper::provision() { setStatusLEDBrightness(WS._config.status_pixel_brightness); // Set device's wireless credentials set_ssid_pass(); - -#ifdef USE_DISPLAY - WS._ui_helper->set_label_status(""); - WS._ui_helper->set_load_bar_icon_complete(loadBarIconFile); -#endif } /**************************************************************************/ @@ -294,24 +266,10 @@ bool Wippersnapper::configAnalogInPinReq( WS._analogIO->initAnalogInputPin(pin, pinMsg->period, pinMsg->pull, pinMsg->analog_read_mode); -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Pin] Reading %s every %0.2f seconds\n", - pinMsg->pin_name, pinMsg->period); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - } else if ( pinMsg->request_type == wippersnapper_pin_v1_ConfigurePinRequest_RequestType_REQUEST_TYPE_DELETE) { WS._analogIO->deinitAnalogPin(pinMsg->direction, pin); - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Pin] De-initialized pin %s\n.", pinMsg->pin_name); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - } else { WS_DEBUG_PRINTLN("ERROR: Could not decode analog pin request!"); is_success = false; @@ -966,10 +924,6 @@ bool cbDecodeServoMsg(pb_istream_t *stream, const pb_field_t *field, &msgServoAttachReq)) { WS_DEBUG_PRINTLN( "ERROR: Could not decode wippersnapper_servo_v1_ServoAttachRequest"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal( - "[Servo ERROR] Could not decode servo request from IO!\n"); -#endif return false; // fail out if we can't decode the request } // execute servo attach request @@ -979,11 +933,6 @@ bool cbDecodeServoMsg(pb_istream_t *stream, const pb_field_t *field, atoi(servoPin), msgServoAttachReq.min_pulse_width, msgServoAttachReq.max_pulse_width, msgServoAttachReq.servo_freq)) { WS_DEBUG_PRINTLN("ERROR: Unable to attach servo to pin!"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal( - "[Servo ERROR] Unable to attach servo to pin! Is it already in " - "use?\n"); -#endif attached = false; } else { WS_DEBUG_PRINT("ATTACHED servo w/minPulseWidth: "); @@ -992,12 +941,6 @@ bool cbDecodeServoMsg(pb_istream_t *stream, const pb_field_t *field, WS_DEBUG_PRINT(msgServoAttachReq.min_pulse_width); WS_DEBUG_PRINT("uS on pin: "); WS_DEBUG_PRINTLN(servoPin); -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Servo] Attached servo on pin %s\n.", - msgServoAttachReq.servo_pin); - WS._ui_helper->add_text_to_terminal(buffer); -#endif } // Create and fill a servo response message @@ -1046,14 +989,6 @@ bool cbDecodeServoMsg(pb_istream_t *stream, const pb_field_t *field, WS_DEBUG_PRINT((int)msgServoWriteReq.pulse_width); WS_DEBUG_PRINT("uS to servo on pin#: "); WS_DEBUG_PRINTLN(servoPin); - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Servo] Writing pulse width of %u uS to pin %s\n.", - (int)msgServoWriteReq.pulse_width, msgServoWriteReq.servo_pin); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - WS._servoComponent->servo_write(atoi(servoPin), (int)msgServoWriteReq.pulse_width); } else if (field->tag == @@ -1074,14 +1009,6 @@ bool cbDecodeServoMsg(pb_istream_t *stream, const pb_field_t *field, char *servoPin = msgServoDetachReq.servo_pin + 1; WS_DEBUG_PRINT("Detaching servo from pin "); WS_DEBUG_PRINTLN(servoPin); - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Servo] Detaching from pin %s\n.", - msgServoDetachReq.servo_pin); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - WS._servoComponent->servo_detach(atoi(servoPin)); } else { WS_DEBUG_PRINTLN("Unable to decode servo message type!"); @@ -1145,10 +1072,6 @@ bool cbPWMDecodeMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) { &msgPWMAttachRequest)) { WS_DEBUG_PRINTLN( "ERROR: Could not decode wippersnapper_pwm_v1_PWMAttachRequest"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal( - "[PWM ERROR]: Could not decode pin attach request!\n"); -#endif return false; // fail out if we can't decode the request } @@ -1159,11 +1082,6 @@ bool cbPWMDecodeMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) { (uint8_t)msgPWMAttachRequest.resolution); if (!attached) { WS_DEBUG_PRINTLN("ERROR: Unable to attach PWM pin"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal( - "[PWM ERROR]: Failed to attach PWM to pin! Is this pin already in " - "use?\n"); -#endif attached = false; } @@ -1194,14 +1112,6 @@ bool cbPWMDecodeMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) { return false; } WS_DEBUG_PRINTLN("Published!"); - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[PWM] Attached on pin %s\n.", - msgPWMResponse.payload.attach_response.pin); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - } else if (field->tag == wippersnapper_signal_v1_PWMRequest_detach_request_tag) { WS_DEBUG_PRINTLN("GOT: PWM Pin Detach"); @@ -1212,23 +1122,11 @@ bool cbPWMDecodeMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) { &msgPWMDetachRequest)) { WS_DEBUG_PRINTLN( "ERROR: Could not decode wippersnapper_pwm_v1_PWMDetachRequest"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal( - "[PWM ERROR] Failed to decode pin detach request from IO!\n"); -#endif return false; // fail out if we can't decode the request } // execute PWM pin detatch request char *pwmPin = msgPWMDetachRequest.pin + 1; WS._pwmComponent->detach(atoi(pwmPin)); - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[PWM] Detached on pin %s\n.", - msgPWMDetachRequest.pin); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - } else if (field->tag == wippersnapper_signal_v1_PWMRequest_write_freq_request_tag) { WS_DEBUG_PRINTLN("GOT: PWM Write Tone"); @@ -1240,13 +1138,8 @@ bool cbPWMDecodeMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) { &msgPWMWriteFreqRequest)) { WS_DEBUG_PRINTLN("ERROR: Could not decode " "wippersnapper_pwm_v1_PWMWriteFrequencyRequest"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal( - "[PWM ERROR] Failed to decode frequency write request from IO!\n"); -#endif return false; // fail out if we can't decode the request } - // execute PWM pin duty cycle write request char *pwmPin = msgPWMWriteFreqRequest.pin + 1; WS_DEBUG_PRINT("Writing frequency: "); @@ -1254,14 +1147,6 @@ bool cbPWMDecodeMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) { WS_DEBUG_PRINT("Hz to pin "); WS_DEBUG_PRINTLN(atoi(pwmPin)); WS._pwmComponent->writeTone(atoi(pwmPin), msgPWMWriteFreqRequest.frequency); - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[PWM] Writing %ld Hz to pin %s\n.", - msgPWMWriteFreqRequest.frequency, msgPWMWriteFreqRequest.pin); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - } else if (field->tag == wippersnapper_signal_v1_PWMRequest_write_duty_request_tag) { WS_DEBUG_PRINTLN("GOT: PWM Write Duty Cycle"); @@ -1274,24 +1159,12 @@ bool cbPWMDecodeMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) { &msgPWMWriteDutyCycleRequest)) { WS_DEBUG_PRINTLN("ERROR: Could not decode " "wippersnapper_pwm_v1_PWMWriteDutyCycleRequest"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal( - "[PWM ERROR] Failed to decode duty cycle write request from IO!\n"); -#endif return false; // fail out if we can't decode the request } // execute PWM duty cycle write request char *pwmPin = msgPWMWriteDutyCycleRequest.pin + 1; WS._pwmComponent->writeDutyCycle( atoi(pwmPin), (int)msgPWMWriteDutyCycleRequest.duty_cycle); - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[PWM] Writing duty cycle %d to pin %d\n.", - (int)msgPWMWriteDutyCycleRequest.duty_cycle, atoi(pwmPin)); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - } else { WS_DEBUG_PRINTLN("Unable to decode PWM message type!"); return false; @@ -1450,9 +1323,6 @@ bool cbDecodePixelsMsg(pb_istream_t *stream, const pb_field_t *field, &msgPixelsCreateReq)) { WS_DEBUG_PRINTLN("ERROR: Could not decode message of type " "wippersnapper_pixels_v1_PixelsCreateRequest!"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal("[Pixel] Error decoding message!\n"); -#endif return false; } @@ -1844,11 +1714,6 @@ void cbErrorTopic(char *errorData, uint16_t len) { if (!WS._mqtt->disconnect()) { WS_DEBUG_PRINTLN("ERROR: Unable to disconnect from MQTT broker!"); } - -#ifdef USE_DISPLAY - WS._ui_helper->show_scr_error("IO Ban Error", errorData); -#endif - // WDT reset WS.haltError("IO MQTT Ban Error"); } @@ -1879,15 +1744,6 @@ void cbThrottleTopic(char *throttleData, uint16_t len) { WS_DEBUG_PRINT(throttleDuration); WS_DEBUG_PRINTLN("ms and blocking command execution."); -#ifdef USE_DISPLAY - char buffer[100]; - snprintf( - buffer, 100, - "[IO ERROR] Device is throttled for %d mS and blocking execution..\n.", - throttleDuration); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - // If throttle duration is less than the keepalive interval, delay for the // full keepalive interval if (throttleDuration < WS_KEEPALIVE_INTERVAL_MS) { @@ -1904,10 +1760,6 @@ void cbThrottleTopic(char *throttleData, uint16_t len) { } } WS_DEBUG_PRINTLN("Device is un-throttled, resumed command execution"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal( - "[IO] Device is un-throttled, resuming...\n"); -#endif } /**************************************************************************/ @@ -2576,10 +2428,6 @@ void Wippersnapper::runNetFSM() { case FSM_NET_CHECK_NETWORK: if (networkStatus() == WS_NET_CONNECTED) { WS_DEBUG_PRINTLN("Connected to WiFi!"); -#ifdef USE_DISPLAY - if (WS._ui_helper->getLoadingState()) - WS._ui_helper->set_load_bar_icon_complete(loadBarIconWifi); -#endif fsmNetwork = FSM_NET_ESTABLISH_MQTT; break; } @@ -2588,19 +2436,10 @@ void Wippersnapper::runNetFSM() { case FSM_NET_ESTABLISH_NETWORK: WS_DEBUG_PRINTLN("Establishing network connection..."); WS_PRINTER.flush(); -#ifdef USE_DISPLAY - if (WS._ui_helper->getLoadingState()) - WS._ui_helper->set_label_status("Connecting to WiFi..."); -#endif // Perform a WiFi scan and check if SSID within // secrets.json is within the scanned SSIDs WS_DEBUG_PRINT("Performing a WiFi scan for SSID..."); if (!check_valid_ssid()) { -#ifdef USE_DISPLAY - WS._ui_helper->show_scr_error("ERROR", - "Unable to find WiFi network listed in " - "the secrets file. Rebooting soon..."); -#endif haltError("ERROR: Unable to find WiFi network, rebooting soon...", WS_LED_STATUS_WIFI_CONNECTING); } @@ -2626,12 +2465,6 @@ void Wippersnapper::runNetFSM() { // Validate connection if (networkStatus() != WS_NET_CONNECTED) { WS_DEBUG_PRINTLN("ERROR: Unable to connect to WiFi!"); -#ifdef USE_DISPLAY - WS._ui_helper->show_scr_error( - "CONNECTION ERROR", - "Unable to connect to WiFi Network. Please check that you entered " - "the WiFi credentials correctly. Rebooting in 5 seconds..."); -#endif haltError("ERROR: Unable to connect to WiFi, rebooting soon...", WS_LED_STATUS_WIFI_CONNECTING); } @@ -2639,10 +2472,6 @@ void Wippersnapper::runNetFSM() { fsmNetwork = FSM_NET_CHECK_NETWORK; break; case FSM_NET_ESTABLISH_MQTT: -#ifdef USE_DISPLAY - if (WS._ui_helper->getLoadingState()) - WS._ui_helper->set_label_status("Connecting to IO..."); -#endif WS._mqtt->setKeepAliveInterval(WS_KEEPALIVE_INTERVAL_MS / 1000); // Attempt to connect maxAttempts = 5; @@ -2672,14 +2501,6 @@ void Wippersnapper::runNetFSM() { maxAttempts--; } if (fsmNetwork != FSM_NET_CHECK_MQTT) { -#ifdef USE_DISPLAY - WS._ui_helper->show_scr_error( - "CONNECTION ERROR", - "Unable to connect to Adafruit.io. If you are repeatedly having " - "this issue, please check that your IO Username and IO Key are set " - "correctly in the secrets file. This device will reboot in 5 " - "seconds..."); -#endif haltError( "ERROR: Unable to connect to Adafruit.IO MQTT, rebooting soon...", WS_LED_STATUS_MQTT_CONNECTING); @@ -2794,9 +2615,6 @@ void Wippersnapper::pingBroker() { // blink status LED every STATUS_LED_KAT_BLINK_TIME millis if (millis() > (_prvKATBlink + STATUS_LED_KAT_BLINK_TIME)) { WS_DEBUG_PRINTLN("STATUS LED BLINK KAT"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal("[NET] Sent KeepAlive ping!\n"); -#endif statusLEDBlink(WS_LED_STATUS_KAT); _prvKATBlink = millis(); } @@ -2994,11 +2812,6 @@ void Wippersnapper::connect() { // Enable WDT after wifi connection as wifiMulti doesnt feed WDT WS.enableWDT(WS_WDT_TIMEOUT); -#ifdef USE_DISPLAY - WS._ui_helper->set_load_bar_icon_complete(loadBarIconCloud); - WS._ui_helper->set_label_status("Sending device info..."); -#endif - // Register hardware with Wippersnapper WS_DEBUG_PRINTLN("Registering hardware with WipperSnapper...") if (!registerBoard()) { @@ -3007,14 +2820,6 @@ void Wippersnapper::connect() { runNetFSM(); WS.feedWDT(); -// switch to monitor screen -#ifdef USE_DISPLAY - WS_DEBUG_PRINTLN("Clearing loading screen..."); - WS._ui_helper->clear_scr_load(); - WS_DEBUG_PRINTLN("building monitor screen..."); - WS._ui_helper->build_scr_monitor(); -#endif - // Initialize Digital IO class WS._digitalGPIO = new Wippersnapper_DigitalGPIO(20); // Initialize Analog IO class diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index e7af45ab7..1c9195fc5 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -121,12 +121,6 @@ #include #endif -// Display -#ifdef USE_DISPLAY -#include "display/ws_display_driver.h" -#include "display/ws_display_ui_helper.h" -#endif - #include "components/display/controller.h" #include "components/ds18x20/ws_ds18x20.h" #include "components/pixels/ws_pixels.h" @@ -234,10 +228,6 @@ class Wippersnapper_DigitalGPIO; class Wippersnapper_AnalogIO; class Wippersnapper_FS; class WipperSnapper_LittleFS; -#ifdef USE_DISPLAY -class ws_display_driver; -class ws_display_ui_helper; -#endif #ifdef ARDUINO_ARCH_ESP32 class ws_ledc; #endif @@ -361,11 +351,6 @@ class Wippersnapper { Wippersnapper_FS *_fileSystem; ///< Instance of Filesystem (native USB) WipperSnapper_LittleFS *_littleFS; ///< Instance of LittleFS Filesystem (non-native USB) -#ifdef USE_DISPLAY - ws_display_driver *_display = nullptr; ///< Instance of display driver class - ws_display_ui_helper *_ui_helper = - nullptr; ///< Instance of display UI helper class -#endif ws_pixels *_ws_pixelsComponent; ///< ptr to instance of ws_pixels class ws_pwm *_pwmComponent; ///< Instance of pwm class ws_servo *_servoComponent; ///< Instance of servo class diff --git a/src/Wippersnapper_Boards.h b/src/Wippersnapper_Boards.h index 9a09a9ff5..ec386adab 100644 --- a/src/Wippersnapper_Boards.h +++ b/src/Wippersnapper_Boards.h @@ -38,7 +38,6 @@ #define BOARD_ID "funhouse" ///< Board ID #define USE_TINYUSB ///< Enable TinyUSB #define USE_STATUS_DOTSTAR ///< Enable DotStar -#define USE_DISPLAY ///< Enable Display #define STATUS_DOTSTAR_PIN_DATA PIN_DOTSTAR_DATA ///< DotStar Data Pin #define STATUS_DOTSTAR_PIN_CLK PIN_DOTSTAR_CLOCK ///< DotStar Clock Pin #define STATUS_DOTSTAR_NUM 5 ///< Number of DotStar LEDs diff --git a/src/components/analogIO/Wippersnapper_AnalogIO.cpp b/src/components/analogIO/Wippersnapper_AnalogIO.cpp index 0a887558d..e6c9000e4 100644 --- a/src/components/analogIO/Wippersnapper_AnalogIO.cpp +++ b/src/components/analogIO/Wippersnapper_AnalogIO.cpp @@ -285,11 +285,6 @@ bool Wippersnapper_AnalogIO::encodePinEvent( pinValVolts); snprintf(buffer, 100, "[Pin] A%d read: %0.2f\n", pinName, pinValVolts); } -// display analog pin read on terminal -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal(buffer); -#endif - // Encode signal message pb_ostream_t stream = pb_ostream_from_buffer(WS._buffer_outgoing, sizeof(WS._buffer_outgoing)); diff --git a/src/components/digitalIO/Wippersnapper_DigitalGPIO.cpp b/src/components/digitalIO/Wippersnapper_DigitalGPIO.cpp index f3ab478d9..577c9780d 100644 --- a/src/components/digitalIO/Wippersnapper_DigitalGPIO.cpp +++ b/src/components/digitalIO/Wippersnapper_DigitalGPIO.cpp @@ -75,12 +75,6 @@ void Wippersnapper_DigitalGPIO::initDigitalPin( WS_DEBUG_PRINT("Configured digital output pin on D"); WS_DEBUG_PRINTLN(pinName); -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Pin] Configured Digital Output on D%u\n", pinName); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - // Initialize LOW #if defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) // The Adafruit Feather ESP8266's built-in LED is reverse wired so setting @@ -109,13 +103,6 @@ void Wippersnapper_DigitalGPIO::initDigitalPin( WS_DEBUG_PRINT("Interval (ms):"); WS_DEBUG_PRINTLN(periodMs); -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, - "[Pin] Configured Digital Input on D%u, polling every %lu mS\n", - pinName, periodMs); - WS._ui_helper->add_text_to_terminal(buffer); -#endif // get current time ulong curTime = millis() - 1; @@ -149,12 +136,6 @@ void Wippersnapper_DigitalGPIO::deinitDigitalPin( WS_DEBUG_PRINT("Deinitializing digital pin "); WS_DEBUG_PRINTLN(pinName); -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Pin] De-initialized D%u\n", pinName); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - if (direction == wippersnapper_pin_v1_ConfigurePinRequest_Direction_DIRECTION_INPUT) { // de-allocate the pin within digital_input_pins[] @@ -209,12 +190,6 @@ void Wippersnapper_DigitalGPIO::digitalWriteSvc(uint8_t pinName, int pinValue) { WS_DEBUG_PRINT(" to "); WS_DEBUG_PRINTLN(pinValue); -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Pin] Writing %d to D%u\n", pinValue, pinName); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - // Write to the GPIO pin #if defined(ARDUINO_ESP8266_ADAFRUIT_HUZZAH) // The Adafruit Feather ESP8266's built-in LED is reverse wired so setting the @@ -249,13 +224,6 @@ void Wippersnapper_DigitalGPIO::processDigitalInputs() { // read the pin int pinVal = digitalReadSvc(_digital_input_pins[i].pinName); -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Pin] Read D%u: %d\n", - _digital_input_pins[i].pinName, pinVal); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - // Create new signal message wippersnapper_signal_v1_CreateSignalRequest _outgoingSignalMsg = wippersnapper_signal_v1_CreateSignalRequest_init_zero; @@ -289,13 +257,6 @@ void Wippersnapper_DigitalGPIO::processDigitalInputs() { WS_DEBUG_PRINT("Executing state-based event on D"); WS_DEBUG_PRINTLN(_digital_input_pins[i].pinName); -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Pin] Read D%u: %d\n", - _digital_input_pins[i].pinName, pinVal); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - // Create new signal message wippersnapper_signal_v1_CreateSignalRequest _outgoingSignalMsg = wippersnapper_signal_v1_CreateSignalRequest_init_zero; diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index d9c1b2c79..58250fd7c 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -57,16 +57,19 @@ class dispDrvSt7789 : public dispDrvBase { */ bool begin() override { -// Special configuration for Feather TFTs +// Special power control configuration for +// boards with built-in TFTs #if defined(TFT_BACKLITE) // turn on backlite pinMode(TFT_BACKLITE, OUTPUT); digitalWrite(TFT_BACKLITE, HIGH); + #if defined(TFT_I2C_POWER) // turn on the TFT / I2C power supply pinMode(TFT_I2C_POWER, OUTPUT); digitalWrite(TFT_I2C_POWER, HIGH); delay(10); + #endif // TFT_I2C_POWER #endif _display = new Adafruit_ST7789(_pin_cs, _pin_dc, _pin_rst); diff --git a/src/components/ds18x20/ws_ds18x20.cpp b/src/components/ds18x20/ws_ds18x20.cpp index 0cfa6e0c5..6aac8fee5 100644 --- a/src/components/ds18x20/ws_ds18x20.cpp +++ b/src/components/ds18x20/ws_ds18x20.cpp @@ -97,13 +97,6 @@ bool ws_ds18x20::addDS18x20( WS_DEBUG_PRINT(msgDs18x20InitReq->onewire_pin); WS_DEBUG_PRINTLN(" with DS18x20 attached!"); -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[DS18x] Attached DS18x20 sensor to pin %s\n", - msgDs18x20InitReq->onewire_pin); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - // Encode and publish response back to broker memset(WS._buffer_outgoing, 0, sizeof(WS._buffer_outgoing)); pb_ostream_t ostream = @@ -148,13 +141,6 @@ void ws_ds18x20::deleteDS18x20( idx); // erase vector and re-allocate } } - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[DS18x] Deleted DS18x20 sensor on pin %s\n", - msgDS18x20DeinitReq->onewire_pin); - WS._ui_helper->add_text_to_terminal(buffer); -#endif } /*************************************************************/ @@ -194,11 +180,6 @@ void ws_ds18x20::update() { if (tempC == DEVICE_DISCONNECTED_C) { WS_DEBUG_PRINTLN("ERROR: Could not read temperature data, is the " "sensor disconnected?"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal( - "[DS18x ERROR] Unable to read temperature, is the sensor " - "disconnected?\n"); -#endif break; } @@ -301,10 +282,6 @@ void ws_ds18x20::update() { return; }; WS_DEBUG_PRINTLN("PUBLISHED!"); -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal(buffer); -#endif - (*iter)->sensorPeriodPrv = curTime; // set prv period } } diff --git a/src/components/i2c/WipperSnapper_I2C.cpp b/src/components/i2c/WipperSnapper_I2C.cpp index 16616f441..62cc167d0 100644 --- a/src/components/i2c/WipperSnapper_I2C.cpp +++ b/src/components/i2c/WipperSnapper_I2C.cpp @@ -1233,9 +1233,6 @@ void WipperSnapper_Component_I2C::displayDeviceEventMessage( default: break; } -#ifdef USE_DISPLAY - WS._ui_helper->add_text_to_terminal(buffer); -#endif } } diff --git a/src/components/pixels/ws_pixels.cpp b/src/components/pixels/ws_pixels.cpp index 2d3b52237..22edefd46 100644 --- a/src/components/pixels/ws_pixels.cpp +++ b/src/components/pixels/ws_pixels.cpp @@ -272,14 +272,6 @@ bool ws_pixels::addStrand( WS_DEBUG_PRINT(pixelsCreateReqMsg->pixels_num); WS_DEBUG_PRINT(" on GPIO #"); WS_DEBUG_PRINTLN(pixelsCreateReqMsg->pixels_pin_neopixel); - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Pixel] Added NeoPixel strand on Pin %s\n.", - pixelsCreateReqMsg->pixels_pin_neopixel); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - publishAddStrandResponse(true, pixelsCreateReqMsg->pixels_pin_neopixel); } else if (pixelsCreateReqMsg->pixels_type == wippersnapper_pixels_v1_PixelsType_PIXELS_TYPE_DOTSTAR) { @@ -314,14 +306,6 @@ bool ws_pixels::addStrand( WS_DEBUG_PRINT(strands[strandIdx].numPixels); WS_DEBUG_PRINT(" on Data GPIO #"); WS_DEBUG_PRINTLN(strands[strandIdx].pinDotStarData); - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Pixel] Added NeoPixel strand on Pin %s\n.", - pixelsCreateReqMsg->pixels_pin_neopixel); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - publishAddStrandResponse(true, pixelsCreateReqMsg->pixels_pin_dotstar_data); } else { WS_DEBUG_PRINTLN("ERROR: Invalid strand type provided!"); @@ -380,13 +364,6 @@ void ws_pixels::deleteStrand( WS_DEBUG_PRINT("Deleted strand on data pin "); WS_DEBUG_PRINTLN(pixelsDeleteMsg->pixels_pin_data); - -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Pixel] Deleted strand on pin %s\n.", - pixelsDeleteMsg->pixels_pin_data); - WS._ui_helper->add_text_to_terminal(buffer); -#endif } /**************************************************************************/ @@ -439,14 +416,6 @@ void ws_pixels::fillStrand( WS_DEBUG_PRINT("Filling color: "); WS_DEBUG_PRINTLN(pixelsWriteMsg->pixels_color); -#ifdef USE_DISPLAY - char buffer[100]; - snprintf(buffer, 100, "[Pixel] Filling strand on pin %s with color %u\n", - pixelsWriteMsg->pixels_pin_data, - (unsigned int)pixelsWriteMsg->pixels_color); - WS._ui_helper->add_text_to_terminal(buffer); -#endif - if (pixelsWriteMsg->pixels_type == wippersnapper_pixels_v1_PixelsType_PIXELS_TYPE_NEOPIXEL) { strands[strandIdx].neoPixelPtr->fill(rgbColorGamma); diff --git a/src/display/symbols/cloud_30px.c b/src/display/symbols/cloud_30px.c deleted file mode 100644 index 9f41981db..000000000 --- a/src/display/symbols/cloud_30px.c +++ /dev/null @@ -1,158 +0,0 @@ -/******************************************************************************* - * Size: 30 px - * Bpp: 4 - * Opts: - ******************************************************************************/ - -#ifdef ARDUINO_FUNHOUSE_ESP32S2 - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include -#endif - -#ifndef CLOUD_30PX -#define CLOUD_30PX 1 -#endif - -#if CLOUD_30PX - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+F0C2 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x67, 0x63, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x19, 0xef, 0xff, 0xff, 0xe9, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x6f, 0xff, 0xfa, 0x75, 0x7a, 0xff, 0xff, 0x73, 0x8a, 0x96, 0x10, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xfc, 0x20, 0x0, - 0x0, 0x1c, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xe, 0xff, 0x90, 0x0, 0x0, 0x0, 0x0, 0x8f, 0xff, 0xff, - 0xff, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xfd, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x9, 0xfc, 0x73, 0x49, 0xff, 0xf7, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xcf, 0xf3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x30, 0x0, 0x0, 0x4f, 0xff, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, - 0xd0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, - 0x80, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, - 0x8, 0xff, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x5, 0xef, 0xff, 0x90, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xff, 0xd0, 0x0, 0x0, - 0x0, 0x6f, 0xff, 0xfc, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x4, 0xff, 0xfe, 0x50, 0x0, 0x5, 0xff, 0xfa, 0x20, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0xaf, 0xff, - 0xf5, 0x0, 0xe, 0xff, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xaf, 0xff, 0x30, 0x6f, 0xfa, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x9, 0xff, 0xb0, 0xbf, 0xf2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdf, 0xf2, 0xdf, - 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf5, 0xff, 0xd0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f, - 0xf8, 0xef, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, 0xf8, 0xbf, 0xf4, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x9f, 0xf6, 0x6f, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xf1, 0xe, 0xff, - 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1b, 0xff, 0x90, 0x4, 0xff, 0xfd, 0x52, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x15, 0xef, 0xfe, 0x0, - 0x0, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe3, 0x0, 0x0, 0x4, 0xdf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, - 0x10, 0x0, 0x0, 0x0, 0x4, 0x9c, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xc9, 0x40, 0x0, 0x0}; - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, - .adv_w = 0, - .box_w = 0, - .box_h = 0, - .ofs_x = 0, - .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, - .adv_w = 600, - .box_w = 38, - .box_h = 27, - .ofs_x = 0, - .ofs_y = -2}}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { - {.range_start = 61634, - .range_length = 1, - .glyph_id_start = 1, - .unicode_list = NULL, - .glyph_id_ofs_list = NULL, - .list_length = 0, - .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY}}; - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LV_VERSION_CHECK(8, 0, 0) -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 4, - .kern_classes = 0, - .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) -const lv_font_t cloud_30px = { -#else -lv_font_t cloud_30px = { -#endif - .get_glyph_dsc = - lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = - lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 27, /*The maximum line height required by the font*/ - .base_line = 2, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc /*The custom font data. Will be accessed by - `get_glyph_bitmap/dsc` */ -}; - -#endif /*#if CLOUD_30PX*/ - -#endif \ No newline at end of file diff --git a/src/display/symbols/errorTriangle.c b/src/display/symbols/errorTriangle.c deleted file mode 100644 index c4d108750..000000000 --- a/src/display/symbols/errorTriangle.c +++ /dev/null @@ -1,492 +0,0 @@ -/******************************************************************************* - * Size: 100 px - * Bpp: 4 - * Opts: - ******************************************************************************/ -#ifdef ARDUINO_FUNHOUSE_ESP32S2 -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include -#endif - -#ifndef ERRORTRIANGLE -#define ERRORTRIANGLE 1 -#endif - -#if ERRORTRIANGLE - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+F071 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x11, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x4, 0xbf, 0xff, 0xea, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xaf, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xaf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf7, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x60, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf9, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa2, 0x0, 0x2b, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x0, 0x0, 0x0, - 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, - 0x0, 0x0, 0x0, 0xd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x8, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, - 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, - 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfe, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, - 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, - 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, - 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, - 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, - 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x70, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, - 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, - 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, - 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0xc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x90, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, - 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, - 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x8, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0xd, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, - 0x9f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xb4, 0x11, 0x4c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x20, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x70, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x44, 0x7d, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x30, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, - 0x0, 0x0, 0x0, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x40, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf9, 0x0, 0x0, 0x0, 0x0, 0x0, 0xaf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfe, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x90, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x0, 0x2f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf2, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, - 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x0, - 0x0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf8, 0x0, 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x60, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x20, 0x0, 0x0, 0xe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf9, 0x0, 0x0, 0x1, 0xaf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb0, 0x0, 0x0, 0x8f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfb, 0x88, 0xbf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x0, - 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfd, 0x0, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xc, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x90, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xd0, 0xe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xb0, 0xb, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x4, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, - 0x0, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf9, 0x0, 0x0, 0x1e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x1, 0xcf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x0, 0x0, 0x0, 0x0, 0x5, - 0xbe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xea, 0x40, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0}; - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, - .adv_w = 0, - .box_w = 0, - .box_h = 0, - .ofs_x = 0, - .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, - .adv_w = 1600, - .box_w = 102, - .box_h = 89, - .ofs_x = -1, - .ofs_y = -7}}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { - {.range_start = 61553, - .range_length = 1, - .glyph_id_start = 1, - .unicode_list = NULL, - .glyph_id_ofs_list = NULL, - .list_length = 0, - .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY}}; - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LV_VERSION_CHECK(8, 0, 0) -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 4, - .kern_classes = 0, - .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) -const lv_font_t errorTriangle = { -#else -lv_font_t errorTriangle = { -#endif - .get_glyph_dsc = - lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = - lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 89, /*The maximum line height required by the font*/ - .base_line = 7, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc /*The custom font data. Will be accessed by - `get_glyph_bitmap/dsc` */ -}; - -#endif /*#if ERRORTRIANGLE*/ - -#endif \ No newline at end of file diff --git a/src/display/symbols/file.c b/src/display/symbols/file.c deleted file mode 100644 index 071f76efa..000000000 --- a/src/display/symbols/file.c +++ /dev/null @@ -1,144 +0,0 @@ -/******************************************************************************* - * Size: 30 px - * Bpp: 4 - * Opts: - ******************************************************************************/ -#ifdef ARDUINO_FUNHOUSE_ESP32S2 - -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include -#endif - -#ifndef FILE -#define FILE 1 -#endif - -#if FILE - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+F1C9 "" */ - 0x0, 0x3, 0x33, 0x33, 0x33, 0x33, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0xb0, 0x0, 0x0, 0x0, 0x5f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xf, 0xb0, 0x0, 0x0, 0xc, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0xff, 0xb0, 0x0, 0x0, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf1, 0xf, 0xff, 0xb0, 0x0, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x10, 0xff, 0xff, 0xb0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf1, 0xf, 0xff, 0xff, 0xb0, 0xf, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x10, 0xff, 0xff, 0xff, 0xb0, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf2, 0x3, 0x33, 0x33, 0x33, 0x1f, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfd, 0xdd, 0xdd, 0xdd, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0x89, 0xff, 0xff, 0xd6, - 0xcf, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff, 0x40, 0xc, 0xff, 0xf3, 0x0, - 0xaf, 0xff, 0xff, 0x8f, 0xff, 0xff, 0x40, 0x1, 0xff, 0xff, 0x70, 0x0, - 0xaf, 0xff, 0xf8, 0xff, 0xff, 0x40, 0x0, 0xcf, 0xff, 0xff, 0x50, 0x0, - 0xbf, 0xff, 0x8f, 0xff, 0xd0, 0x0, 0x9f, 0xff, 0xff, 0xff, 0x20, 0x4, - 0xff, 0xf8, 0xff, 0xff, 0x30, 0x1, 0xdf, 0xff, 0xff, 0x60, 0x0, 0xaf, - 0xff, 0x8f, 0xff, 0xfe, 0x20, 0x1, 0xff, 0xff, 0x80, 0x0, 0x9f, 0xff, - 0xf8, 0xff, 0xff, 0xfe, 0x20, 0xb, 0xff, 0xf3, 0x0, 0x9f, 0xff, 0xff, - 0x8f, 0xff, 0xff, 0xfe, 0x66, 0xff, 0xff, 0xb4, 0xaf, 0xff, 0xff, 0xf8, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8e, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xaf, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x31, 0xef, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x1, 0x8c, 0xcc, - 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xca, 0x50, 0x0}; - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, - .adv_w = 0, - .box_w = 0, - .box_h = 0, - .ofs_x = 0, - .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, - .adv_w = 360, - .box_w = 23, - .box_h = 31, - .ofs_x = 0, - .ofs_y = -4}}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { - {.range_start = 61897, - .range_length = 1, - .glyph_id_start = 1, - .unicode_list = NULL, - .glyph_id_ofs_list = NULL, - .list_length = 0, - .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY}}; - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LV_VERSION_CHECK(8, 0, 0) -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 4, - .kern_classes = 0, - .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) -const lv_font_t file = { -#else -lv_font_t file = { -#endif - .get_glyph_dsc = - lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = - lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 31, /*The maximum line height required by the font*/ - .base_line = 4, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc /*The custom font data. Will be accessed by - `get_glyph_bitmap/dsc` */ -}; - -#endif - -#endif /*#if FILE*/ diff --git a/src/display/symbols/turtle_16.c b/src/display/symbols/turtle_16.c deleted file mode 100644 index 0729e503a..000000000 --- a/src/display/symbols/turtle_16.c +++ /dev/null @@ -1,124 +0,0 @@ -/******************************************************************************* - * Size: 16 px - * Bpp: 4 - * Opts: - ******************************************************************************/ -#ifdef ARDUINO_FUNHOUSE_ESP32S2 -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include -#endif - -#ifndef TURTLE_16 -#define TURTLE_16 1 -#endif - -#if TURTLE_16 - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+F726 "" */ - 0x0, 0x1, 0x9c, 0xfc, 0x91, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4e, 0xff, - 0xff, 0xfe, 0x30, 0x0, 0x0, 0x0, 0x1, 0xef, 0xff, 0xff, 0xff, 0xe1, - 0x8, 0x86, 0x10, 0x9, 0xff, 0xff, 0xff, 0xff, 0xf9, 0xf, 0xff, 0xe3, - 0xc, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf, 0xff, 0xfc, 0xf, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf, 0xf8, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf, 0xff, 0xff, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf, 0xff, 0xff, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x0, 0x0, 0xff, 0xff, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, - 0x0, 0xff, 0xff, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, - 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0}; - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, - .adv_w = 0, - .box_w = 0, - .box_h = 0, - .ofs_x = 0, - .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, - .adv_w = 288, - .box_w = 18, - .box_h = 14, - .ofs_x = 0, - .ofs_y = -1}}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { - {.range_start = 63270, - .range_length = 1, - .glyph_id_start = 1, - .unicode_list = NULL, - .glyph_id_ofs_list = NULL, - .list_length = 0, - .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY}}; - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LV_VERSION_CHECK(8, 0, 0) -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 4, - .kern_classes = 0, - .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) -const lv_font_t turtle_16 = { -#else -lv_font_t turtle_16 = { -#endif - .get_glyph_dsc = - lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = - lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 14, /*The maximum line height required by the font*/ - .base_line = 1, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc /*The custom font data. Will be accessed by - `get_glyph_bitmap/dsc` */ -}; - -#endif /*#if TURTLE_16*/ - -#endif \ No newline at end of file diff --git a/src/display/symbols/turtle_30px.c b/src/display/symbols/turtle_30px.c deleted file mode 100644 index e3fe5fca8..000000000 --- a/src/display/symbols/turtle_30px.c +++ /dev/null @@ -1,152 +0,0 @@ -/******************************************************************************* - * Size: 30 px - * Bpp: 4 - * Opts: - ******************************************************************************/ -#ifdef ARDUINO_FUNHOUSE_ESP32S2 -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include -#endif - -#ifndef TURTLE_30PX -#define TURTLE_30PX 1 -#endif - -#if TURTLE_30PX - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+F726 "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6b, 0xff, 0xff, - 0xd9, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x6e, 0xff, 0xff, 0xff, 0xff, 0xfa, 0x10, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xe3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0x0, 0x0, 0x15, 0x63, 0x0, 0x0, 0x0, 0xe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf6, 0x0, 0x6, 0xff, 0xff, 0xd3, 0x0, 0x0, - 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x0, 0x3f, - 0xff, 0xff, 0xff, 0x50, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x20, 0x8f, 0xff, 0xff, 0xff, 0xe1, 0x0, 0xef, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x60, 0xaf, 0xff, 0xff, - 0xff, 0xf7, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x70, 0xaf, 0xff, 0x87, 0xff, 0xfa, 0x1, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0xaf, 0xff, 0x42, 0xff, 0xfc, - 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - 0xaf, 0xff, 0xff, 0xff, 0xfb, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x80, 0xbf, 0xff, 0xff, 0xff, 0xf7, 0x0, 0xdf, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0xef, 0xff, - 0xff, 0xff, 0xc0, 0x0, 0x2b, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, - 0xdd, 0xc6, 0x7, 0xff, 0xff, 0xdd, 0xb7, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xf6, 0x0, 0x0, - 0x0, 0x18, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xbe, - 0xff, 0xff, 0xd0, 0x0, 0x0, 0x0, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x20, 0x0, 0x0, 0x0, 0xef, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, - 0x0, 0x0, 0x0, 0x0, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0xb5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0xff, - 0xff, 0xff, 0xf5, 0x1d, 0xff, 0xff, 0xff, 0xb0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xf4, 0xd, 0xff, 0xff, 0xff, - 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, - 0xf4, 0xd, 0xff, 0xff, 0xff, 0xa0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x2, 0xff, 0xff, 0xff, 0xf4, 0xc, 0xff, 0xff, 0xff, 0xa0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xdf, 0xff, 0xff, 0xe0, 0x8, - 0xff, 0xff, 0xff, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x29, 0xbb, 0xb9, 0x20, 0x0, 0x7b, 0xbb, 0xb5, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0}; - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, - .adv_w = 0, - .box_w = 0, - .box_h = 0, - .ofs_x = 0, - .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, - .adv_w = 540, - .box_w = 34, - .box_h = 27, - .ofs_x = 0, - .ofs_y = -2}}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { - {.range_start = 63270, - .range_length = 1, - .glyph_id_start = 1, - .unicode_list = NULL, - .glyph_id_ofs_list = NULL, - .list_length = 0, - .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY}}; - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LV_VERSION_CHECK(8, 0, 0) -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 4, - .kern_classes = 0, - .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) -const lv_font_t turtle_30px = { -#else -lv_font_t turtle_30px = { -#endif - .get_glyph_dsc = - lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = - lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 27, /*The maximum line height required by the font*/ - .base_line = 2, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc /*The custom font data. Will be accessed by - `get_glyph_bitmap/dsc` */ -}; - -#endif /*#if TURTLE_30PX*/ - -#endif \ No newline at end of file diff --git a/src/display/symbols/wifi_30px.c b/src/display/symbols/wifi_30px.c deleted file mode 100644 index ca55fb199..000000000 --- a/src/display/symbols/wifi_30px.c +++ /dev/null @@ -1,157 +0,0 @@ -/******************************************************************************* - * Size: 30 px - * Bpp: 4 - * Opts: - ******************************************************************************/ -#ifdef ARDUINO_FUNHOUSE_ESP32S2 -#ifdef LV_LVGL_H_INCLUDE_SIMPLE -#include "lvgl.h" -#else -#include -#endif - -#ifndef WIFI_30PX -#define WIFI_30PX 1 -#endif - -#if WIFI_30PX - -/*----------------- - * BITMAPS - *----------------*/ - -/*Store the image of the glyphs*/ -static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { - /* U+F1EB "" */ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x12, 0x11, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x59, 0xce, 0xff, 0xff, 0xff, 0xdb, 0x72, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x6b, 0xff, 0xff, 0xff, - 0xdb, 0xce, 0xff, 0xff, 0xfd, 0x84, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x19, 0xff, 0xfe, 0x95, 0x20, 0x0, 0x0, 0x0, 0x13, 0x7c, - 0xff, 0xfc, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xfe, 0x83, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x5c, 0xff, 0xb3, 0x0, - 0x0, 0x0, 0x0, 0x4, 0xef, 0xf8, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x4, 0xcf, 0xf9, 0x0, 0x0, 0x0, 0x6, 0xff, - 0x91, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x5e, 0xfc, 0x10, 0x0, 0x9, 0xff, 0x40, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0xfd, 0x20, - 0xb, 0xfd, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x9, 0xff, 0x20, 0xcb, 0x10, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x6, 0xe4, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x16, 0xac, - 0xef, 0xed, 0xb8, 0x30, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x5, 0xcf, 0xff, 0xff, 0xef, 0xff, 0xff, 0xe8, - 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4d, - 0xff, 0xd8, 0x31, 0x0, 0x0, 0x26, 0xbf, 0xff, 0x70, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8f, 0xfc, 0x30, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x18, 0xff, 0xc1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0xbf, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xbf, - 0xe3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xd2, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9f, 0xc0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x61, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x44, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x17, 0xa9, 0x30, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x1e, 0xff, 0xff, 0x60, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa, 0xfb, 0x36, - 0xff, 0x10, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x8, 0xf5, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0xf, 0xf0, 0x0, 0x7f, 0x50, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xbf, 0x91, 0x3e, 0xf1, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x2, 0xff, 0xff, 0xf7, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, - 0x9d, 0xb5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; - -/*--------------------- - * GLYPH DESCRIPTION - *--------------------*/ - -static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { - {.bitmap_index = 0, - .adv_w = 0, - .box_w = 0, - .box_h = 0, - .ofs_x = 0, - .ofs_y = 0} /* id = 0 reserved */, - {.bitmap_index = 0, - .adv_w = 600, - .box_w = 39, - .box_h = 27, - .ofs_x = -1, - .ofs_y = -2}}; - -/*--------------------- - * CHARACTER MAPPING - *--------------------*/ - -/*Collect the unicode lists and glyph_id offsets*/ -static const lv_font_fmt_txt_cmap_t cmaps[] = { - {.range_start = 61931, - .range_length = 1, - .glyph_id_start = 1, - .unicode_list = NULL, - .glyph_id_ofs_list = NULL, - .list_length = 0, - .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY}}; - -/*-------------------- - * ALL CUSTOM DATA - *--------------------*/ - -#if LV_VERSION_CHECK(8, 0, 0) -/*Store all the custom data of the font*/ -static lv_font_fmt_txt_glyph_cache_t cache; -static const lv_font_fmt_txt_dsc_t font_dsc = { -#else -static lv_font_fmt_txt_dsc_t font_dsc = { -#endif - .glyph_bitmap = glyph_bitmap, - .glyph_dsc = glyph_dsc, - .cmaps = cmaps, - .kern_dsc = NULL, - .kern_scale = 0, - .cmap_num = 1, - .bpp = 4, - .kern_classes = 0, - .bitmap_format = 0, -#if LV_VERSION_CHECK(8, 0, 0) - .cache = &cache -#endif -}; - -/*----------------- - * PUBLIC FONT - *----------------*/ - -/*Initialize a public general font descriptor*/ -#if LV_VERSION_CHECK(8, 0, 0) -const lv_font_t wifi_30px = { -#else -lv_font_t wifi_30px = { -#endif - .get_glyph_dsc = - lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ - .get_glyph_bitmap = - lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ - .line_height = 27, /*The maximum line height required by the font*/ - .base_line = 2, /*Baseline measured from the bottom of the line*/ -#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) - .subpx = LV_FONT_SUBPX_NONE, -#endif -#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 - .underline_position = 0, - .underline_thickness = 0, -#endif - .dsc = &font_dsc /*The custom font data. Will be accessed by - `get_glyph_bitmap/dsc` */ -}; - -#endif /*#if WIFI_30PX*/ - -#endif \ No newline at end of file diff --git a/src/display/ws_display_driver.cpp b/src/display/ws_display_driver.cpp deleted file mode 100644 index c3b8dbe09..000000000 --- a/src/display/ws_display_driver.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/*! - * @file ws_display_driver.cpp - * - * Wippersnapper LVGL Display Driver - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2023 for Adafruit Industries. - * - * BSD license, all text here must be included in any redistribution. - * - */ -#ifdef ARDUINO_FUNHOUSE_ESP32S2 -#include "ws_display_driver.h" - -/**************************************************************************/ -/*! - @brief Creates a new WipperSnapper display driver object from a - configuration struct. - @param config - Configuration struct., from FS.parseDisplayConfig(); -*/ -/**************************************************************************/ -ws_display_driver::ws_display_driver(displayConfig config) { - // dynamically create the display driver from the configuration file - if (strcmp(config.driver, "ST7789") == 0) { - WS_DEBUG_PRINTLN("Creating ST7789 driver"); - // create a new ST7789 driver - _tft_st7789 = new Adafruit_ST7789((uint8_t)config.spiConfig.pinCs, - (uint8_t)config.spiConfig.pinDc, - (uint8_t)config.spiConfig.pinRst); - } else { - Serial.println("ERROR: Display driver type not implemented!"); - } - - // set display resolution and rotation - setResolution(config.width, config.height); - setRotation(config.rotation); -} - -/**************************************************************************/ -/*! - @brief Deletes a new WipperSnapper display driver object. -*/ -/**************************************************************************/ -ws_display_driver::~ws_display_driver() { - if (_tft_st7789 != nullptr) { - delete _tft_st7789; - } -} - -/**************************************************************************/ -/*! - @brief Enables LVGL logging using the usb serial. Must be called - AFTER calling Serial.begin(). -*/ -/**************************************************************************/ -void ws_display_driver::enableLogging() {} - -/**************************************************************************/ -/*! - @brief Sets the display's rotation mode. - @param rotationMode - The index for rotation (0-3 inclusive). -*/ -/**************************************************************************/ -void ws_display_driver::setRotation(uint8_t rotationMode) { - _displayRotationMode = rotationMode; -} - -/**************************************************************************/ -/*! - @brief Sets the display resolution, must be called BEFORE begin()! - @param displayWidth - The width of the display, in pixels. - @param displayHeight - The height of the display, in pixels. -*/ -/**************************************************************************/ -void ws_display_driver::setResolution(uint16_t displayWidth, - uint16_t displayHeight) { - _displayWidth = displayWidth; - _displayHeight = displayHeight; -} - -/**************************************************************************/ -/*! - @brief Initializes the display and the lvgl_glue driver. - @returns True if LVGL_Glue began successfully, False otherwise. -*/ -/**************************************************************************/ -bool ws_display_driver::begin() { - // initialize display driver - if (_tft_st7789 != nullptr) { - WS_DEBUG_PRINTLN("Initialize ST7789 driver"); - _tft_st7789->init(_displayWidth, _displayHeight); - } else { - Serial.println("ERROR: Unable to initialize the display driver!"); - return false; - } - -// Hardware-specific display commands -#ifdef ARDUINO_FUNHOUSE_ESP32S2 - pinMode(TFT_BACKLIGHT, OUTPUT); - digitalWrite(TFT_BACKLIGHT, HIGH); -#endif // ARDUINO_FUNHOUSE_ESP32S2 - - // initialize lvgl_glue - WS_DEBUG_PRINTLN("Initialize LVGL"); - _glue = new Adafruit_LvGL_Glue(); - LvGLStatus status = _glue->begin(_tft_st7789); - WS_DEBUG_PRINT("LVGL RC: "); - WS_DEBUG_PRINTLN((int)status); - - // check if lvgl initialized correctly - if (status != LVGL_OK) { - Serial.printf("LVGL_Glue error: %d\r\n", (int)status); - return false; - } - - esp32_lvgl_acquire(); - lv_obj_set_style_bg_color(lv_scr_act(), lv_color_white(), LV_STATE_DEFAULT); - esp32_lvgl_release(); - return true; -} - -/**************************************************************************/ -/*! - @brief Acquires the LVGL_Glue lock. -*/ -/**************************************************************************/ -void ws_display_driver::esp32_lvgl_acquire() { _glue->lvgl_acquire(); } - -/**************************************************************************/ -/*! - @brief Releases the LVGL_Glue lock. -*/ -/**************************************************************************/ -void ws_display_driver::esp32_lvgl_release() { _glue->lvgl_release(); } - -#endif \ No newline at end of file diff --git a/src/display/ws_display_driver.h b/src/display/ws_display_driver.h deleted file mode 100644 index 853119c78..000000000 --- a/src/display/ws_display_driver.h +++ /dev/null @@ -1,56 +0,0 @@ -/*! - * @file ws_display_driver.h - * - * Wippersnapper display driver - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2023 for Adafruit Industries. - * - * BSD license, all text here must be included in any redistribution. - * - */ -#ifndef WIPPERSNAPPER_DISPLAY_H -#define WIPPERSNAPPER_DISPLAY_H - -#include "Wippersnapper.h" -#include "provisioning/Config.h" -#include // Always include this BEFORE lvgl.h! -#include -#include - -LV_FONT_DECLARE(errorTriangle); ///< Error triangle symbol/font - -class Wippersnapper; // fwd decl - -/***************************************************************************/ -/*! - @brief Display driver for LVGL and LVGL_Glue in WipperSnapper. -*/ -/***************************************************************************/ -class ws_display_driver { -public: - ws_display_driver(){}; - ws_display_driver(displayConfig config); - ~ws_display_driver(); - - bool begin(); - void setResolution(uint16_t displayWidth, uint16_t displayHeight); - void setRotation(uint8_t rotationMode); - void enableLogging(); - Adafruit_LvGL_Glue *_glue; ///< LVGL glue object - void esp32_lvgl_acquire(); - void esp32_lvgl_release(); - -private: - Adafruit_ST7789 *_tft_st7789 = nullptr; ///< Adafruit ST7789 display driver - uint16_t _displayWidth; ///< Display width - uint16_t _displayHeight; ///< Display height - uint8_t - _displayRotationMode; ///< Display rotation (mode, not number in degrees) -}; -extern Wippersnapper WS; - -#endif // WIPPERSNAPPER_DISPLAY_H \ No newline at end of file diff --git a/src/display/ws_display_tooltips.h b/src/display/ws_display_tooltips.h deleted file mode 100644 index afe01454f..000000000 --- a/src/display/ws_display_tooltips.h +++ /dev/null @@ -1,28 +0,0 @@ -/*! - * @file ws_display_tooltips.h - * - * Wippersnapper tooltips for the loading screen on a display - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2023 for Adafruit Industries. - * - * BSD license, all text here must be included in any redistribution. - * - */ -#ifndef WS_LOADING_TOOLTIPS_H -#define WS_LOADING_TOOLTIPS_H - -#define WS_LOADING_TIP_1 \ - "Name components in IO using emojis to differentiate them!" ///< Loading tip -#define WS_LOADING_TIP_2 \ - "WipperSnapper now supports TFT displays on some boards (more to come)." ///< Loading tip 2 -#define WS_LOADING_TIP_3 \ - "Getting throttle errors? Try reducing a sensor's polling time." ///< Loading - ///< tip 3 -#define WS_LOADING_TIP_4 \ - "\"Be quick, but don't hurry\" - John Wooden " ///< Loading tip 4 - -#endif // WS_LOADING_TOOLTIPS_H \ No newline at end of file diff --git a/src/display/ws_display_ui_helper.cpp b/src/display/ws_display_ui_helper.cpp deleted file mode 100644 index bfc9fc11b..000000000 --- a/src/display/ws_display_ui_helper.cpp +++ /dev/null @@ -1,472 +0,0 @@ -/*! - * @file ws_display_ui_helper.cpp - * - * LVGL UI Helper class for WipperSnapper - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2023 for Adafruit Industries. - * - * BSD license, all text here must be included in any redistribution. - * - */ -#ifdef ARDUINO_FUNHOUSE_ESP32S2 -#include "ws_display_ui_helper.h" - -/********************** - * STATIC VARIABLES - **********************/ -/* Loading screen */ -static lv_obj_t *lblIconFile; -static lv_obj_t *lblIconWiFi; -static lv_obj_t *labelTurtleBar; -static lv_obj_t *labelCloudBar; -static lv_obj_t *lblStatusText; -static lv_obj_t *lblTipText; -static lv_style_t styleIconFile; -static lv_style_t styleIconWiFi; -static lv_style_t styleIconTurtleStatusbar; -static lv_style_t styleIconCloud; - -/* Error screen */ -static lv_obj_t *labelErrorTriangle; -static lv_obj_t *labelErrorHeader; -static lv_obj_t *labelErrorBody; -static lv_style_t styleErrorTriangle; -static lv_style_t styleLabelErrorLarge; -static lv_style_t styleLabelErrorSmall; - -/* Monitor screen */ -static lv_obj_t *statusbar_icon_bat; -static lv_obj_t *statusbar_icon_wifi; -static lv_obj_t *terminalLabel; -static lv_style_t styleTerminalLabel; - -/********************** - * Timers - **********************/ -static lv_timer_t *timerLoadTips; - -static char terminalTextBuffer[MAX_CONSOLE_TEXT_LEN + - 1]; ///< Contains all text actively displayed on - ///< the terminal screen - -static const char *loading_tips[4] = { - WS_LOADING_TIP_1, WS_LOADING_TIP_2, WS_LOADING_TIP_3, - WS_LOADING_TIP_4}; ///< Holds the loading "tips" - -/**************************************************************************/ -/*! - @brief Changes a label every 2 seconds to a new, random, tip. - @param timer - The lv_timer tied to this callback, timerLoadTips. -*/ -/**************************************************************************/ -void lv_timer_tips_cb(lv_timer_t *timer) { - Serial.println("Timer tips cb called"); - long tipNum = random(0, sizeof(loading_tips) / sizeof(loading_tips[0])); - lv_label_set_text(lblTipText, loading_tips[tipNum]); -} - -/**************************************************************************/ -/*! - @brief Callback for updating the status label on the loading screen. - @param event - Callback data. -*/ -/**************************************************************************/ -static void label_status_cb(lv_event_t *event) { - Serial.println("eventcb called!"); - const char **charPtr{static_cast(lv_event_get_param(event))}; - Serial.print("text: "); - Serial.println(*charPtr); - lv_label_set_text(lblStatusText, *charPtr); -} - -/**************************************************************************/ -/*! - @brief Sets the text of the status label on the loading screen. - @param text - Desired text to write to the status label. -*/ -/**************************************************************************/ -void ws_display_ui_helper::set_label_status(const char *text) { - Serial.print("set_label_status (text): "); - Serial.println(text); - _dispDriver->esp32_lvgl_acquire(); - lv_event_send(lblStatusText, LV_EVENT_REFRESH, &text); - _dispDriver->esp32_lvgl_release(); -} - -/**************************************************************************/ -/*! - @brief Pauses and deletes the loading tip callback timer. -*/ -/**************************************************************************/ -void ws_display_ui_helper::remove_tip_timer() { - lv_timer_pause(timerLoadTips); - lv_timer_del(timerLoadTips); -} - -/**************************************************************************/ -/*! - @brief Sets the screen's background to a black color. -*/ -/**************************************************************************/ -void ws_display_ui_helper::set_bg_black() { - _dispDriver->esp32_lvgl_acquire(); - lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), LV_STATE_DEFAULT); - _dispDriver->esp32_lvgl_release(); -} - -/**************************************************************************/ -/*! - @brief Sets the color of an icon on the loading screen to green. - @param iconType - Desired icon. -*/ -/**************************************************************************/ -void ws_display_ui_helper::set_load_bar_icon_complete(loadBarIcons iconType) { - static lv_style_t *styleIcon; - static lv_obj_t *objIcon; - - switch (iconType) { - case loadBarIconFile: - styleIcon = &styleIconFile; - objIcon = lblIconFile; - break; - case loadBarIconWifi: - styleIcon = &styleIconWiFi; - objIcon = lblIconWiFi; - break; - case loadBarIconCloud: - styleIcon = &styleIconCloud; - objIcon = labelCloudBar; - break; - case loadBarIconTurtle: - styleIcon = &styleIconTurtleStatusbar; - objIcon = labelTurtleBar; - break; - default: - Serial.println("ERROR: Undefined iconType!"); - return; - } - _dispDriver->esp32_lvgl_acquire(); - // set icon's color and refresh - lv_style_set_text_color(styleIcon, lv_palette_main(LV_PALETTE_GREEN)); - lv_obj_refresh_style(objIcon, LV_PART_MAIN, LV_STYLE_PROP_ANY); - _dispDriver->esp32_lvgl_release(); -} - -/**************************************************************************/ -/*! - @brief Returns the loading screen's state. - @returns The loading state, True if loading screen is active, - False otherwise. -*/ -/**************************************************************************/ -bool ws_display_ui_helper::getLoadingState() { return _loadingState; } - -/**************************************************************************/ -/*! - @brief Builds and displays the loading screen. -*/ -/**************************************************************************/ -void ws_display_ui_helper::show_scr_load() { - _dispDriver->esp32_lvgl_acquire(); - // Icon bar - const lv_coord_t iconBarXStart = - 20; // Coordinate where the icon bar begins, on the X axis - const lv_coord_t iconBarYOffset = 5; // Vertical offset from top of screen - const int iconBarXSpaces = 40; // Horizontal spaces between icons - - // add symbol_code (30px) to represent settings.json - lblIconFile = lv_label_create(lv_scr_act()); - lv_label_set_text(lblIconFile, SYMBOL_CODE); - // formatting - lv_style_init(&styleIconFile); - lv_style_set_text_color(&styleIconFile, lv_palette_main(LV_PALETTE_GREY)); - lv_style_set_text_font(&styleIconFile, &file); - lv_obj_add_style(lblIconFile, &styleIconFile, LV_PART_MAIN); - lv_obj_align(lblIconFile, LV_ALIGN_TOP_LEFT, iconBarXStart, iconBarYOffset); - - // add symbol_wifi (30px) to represent wifi connect - lblIconWiFi = lv_label_create(lv_scr_act()); - lv_label_set_text(lblIconWiFi, SYMBOL_WIFI); - lv_style_init(&styleIconWiFi); - lv_style_set_text_color(&styleIconWiFi, lv_palette_main(LV_PALETTE_GREY)); - lv_style_set_text_font(&styleIconWiFi, &wifi_30px); - lv_obj_add_style(lblIconWiFi, &styleIconWiFi, LV_PART_MAIN); - lv_obj_align(lblIconWiFi, LV_ALIGN_TOP_LEFT, iconBarXStart + iconBarXSpaces, - iconBarYOffset); - - // Add cloud - labelCloudBar = lv_label_create(lv_scr_act()); - lv_label_set_text(labelCloudBar, SYMBOL_CLOUD); - - lv_style_init(&styleIconCloud); - lv_style_set_text_color(&styleIconCloud, lv_palette_main(LV_PALETTE_GREY)); - lv_style_set_text_font(&styleIconCloud, &cloud_30px); - lv_obj_add_style(labelCloudBar, &styleIconCloud, LV_PART_MAIN); - lv_obj_align(labelCloudBar, LV_ALIGN_TOP_LEFT, 120, iconBarYOffset); - - // Add turtle - labelTurtleBar = lv_label_create(lv_scr_act()); - lv_label_set_text(labelTurtleBar, SYMBOL_TURTLE30PX); - - lv_style_init(&styleIconTurtleStatusbar); - lv_style_set_text_color(&styleIconTurtleStatusbar, - lv_palette_main(LV_PALETTE_GREY)); - lv_style_set_text_font(&styleIconTurtleStatusbar, &turtle_30px); - lv_obj_add_style(labelTurtleBar, &styleIconTurtleStatusbar, LV_PART_MAIN); - lv_obj_align(labelTurtleBar, LV_ALIGN_TOP_LEFT, 180, iconBarYOffset); - - // Add status text label underneath the top loading bar - lblStatusText = lv_label_create(lv_scr_act()); - lv_label_set_long_mode(lblStatusText, LV_LABEL_LONG_WRAP); - lv_obj_set_style_text_font(lblStatusText, &lv_font_montserrat_20, 0); - lv_obj_set_style_text_color(lblStatusText, lv_color_white(), LV_PART_MAIN); - lv_label_set_text(lblStatusText, "\0"); - lv_obj_align(lblStatusText, LV_ALIGN_TOP_MID, 0, 50); - lv_obj_add_event_cb(lblStatusText, label_status_cb, LV_EVENT_REFRESH, NULL); - - // Add loading tooltip text label - lblTipText = lv_label_create(lv_scr_act()); - lv_label_set_long_mode(lblTipText, LV_LABEL_LONG_WRAP); - lv_obj_set_style_text_font(lblTipText, &lv_font_montserrat_18, 0); - lv_obj_set_width(lblTipText, - 230); // TODO: This should match display width - 10px - lv_obj_set_style_text_color(lblTipText, lv_color_white(), LV_PART_MAIN); - lv_label_set_text(lblTipText, "\0"); - lv_obj_align(lblTipText, LV_ALIGN_BOTTOM_LEFT, 0, -40); - timerLoadTips = lv_timer_create(lv_timer_tips_cb, 3000, NULL); - - _dispDriver->esp32_lvgl_release(); - - _loadingState = true; // using the loading screen state -} - -/**************************************************************************/ -/*! - @brief Deletes all objects/styles off the load screen and frees - their resources. -*/ -/**************************************************************************/ -void ws_display_ui_helper::clear_scr_load() { - Serial.println("clear_scr_load"); - _dispDriver->esp32_lvgl_acquire(); - // Delete icons - lv_obj_del(lblStatusText); - lv_obj_del(lblIconWiFi); - lv_obj_del(lblIconFile); - lv_obj_del(labelTurtleBar); - lv_obj_del(labelCloudBar); - // Clear all properties from styles and free all allocated memory - lv_style_reset(&styleIconWiFi); - lv_style_reset(&styleIconFile); - lv_style_reset(&styleIconCloud); - lv_style_reset(&styleIconTurtleStatusbar); - // Stop the loading tip timer and delete the label - remove_tip_timer(); - lv_obj_del(lblTipText); - _dispDriver->esp32_lvgl_release(); - _loadingState = false; // no longer using the loading screen state -} - -/**************************************************************************/ -/*! - @brief Build and display an error screen. - @param lblError - The generic error. - @param lblDesc - Instructions or steps to resolve the error. -*/ -/**************************************************************************/ -void ws_display_ui_helper::show_scr_error(const char *lblError, - const char *lblDesc) { - Serial.println("show_scr_error"); - // clear the active loading screen (for now, will eventually expand to take in - // a scr obj.) - - clear_scr_load(); - _dispDriver->esp32_lvgl_acquire(); - - // Create error symbol - labelErrorTriangle = lv_label_create(lv_scr_act()); - lv_label_set_text(labelErrorTriangle, SYMBOL_ERROR_TRIANGLE); - - lv_style_init(&styleErrorTriangle); - lv_style_set_text_color(&styleErrorTriangle, lv_color_white()); - lv_style_set_text_font(&styleErrorTriangle, &errorTriangle); - lv_obj_add_style(labelErrorTriangle, &styleErrorTriangle, LV_PART_MAIN); - lv_obj_align(labelErrorTriangle, LV_ALIGN_TOP_MID, 0, 5); - - // Add error label (large) - labelErrorHeader = lv_label_create(lv_scr_act()); - lv_label_set_text(labelErrorHeader, lblError); - - lv_style_init(&styleLabelErrorLarge); - lv_style_set_text_color(&styleLabelErrorLarge, lv_color_white()); - lv_style_set_text_font(&styleLabelErrorLarge, &lv_font_montserrat_18); - lv_obj_add_style(labelErrorHeader, &styleLabelErrorLarge, LV_PART_MAIN); - lv_obj_align(labelErrorHeader, LV_ALIGN_CENTER, 0, -5); - - // Add error label (small) - labelErrorBody = lv_label_create(lv_scr_act()); - lv_label_set_long_mode(labelErrorBody, LV_LABEL_LONG_WRAP); - lv_label_set_text(labelErrorBody, lblDesc); - - lv_style_init(&styleLabelErrorSmall); - lv_style_set_text_color(&styleLabelErrorSmall, lv_color_white()); - lv_style_set_text_font(&styleLabelErrorSmall, &lv_font_montserrat_12); - lv_obj_add_style(labelErrorBody, &styleLabelErrorSmall, LV_PART_MAIN); - // set_width used by LABEL_LONG_WRAP - lv_obj_set_width(labelErrorBody, 220); - lv_obj_align(labelErrorBody, LV_ALIGN_CENTER, -3, 55); - - _dispDriver->esp32_lvgl_release(); -} - -/**************************************************************************/ -/*! - @brief Build and display the monitor screen -*/ -/**************************************************************************/ -void ws_display_ui_helper::build_scr_monitor() { - _dispDriver->esp32_lvgl_acquire(); - - // add canvas to create a status bar - lv_obj_t *canvas = lv_canvas_create(lv_scr_act()); - static uint8_t buffer[LV_CANVAS_BUF_SIZE_TRUE_COLOR(240, 25)]; - lv_canvas_set_buffer(canvas, buffer, 240, 25, LV_IMG_CF_TRUE_COLOR); - lv_canvas_fill_bg(canvas, lv_color_black(), LV_OPA_COVER); - lv_draw_rect_dsc_t rect_dsc; - rect_dsc.bg_color = lv_palette_main(LV_PALETTE_GREY); - rect_dsc.bg_opa = LV_OPA_COVER; - lv_draw_rect_dsc_init(&rect_dsc); - lv_canvas_draw_rect(canvas, 0, 0, 240, 25, &rect_dsc); - - // Add battery icon to status bar - statusbar_icon_bat = lv_label_create(lv_scr_act()); - lv_label_set_text(statusbar_icon_bat, LV_SYMBOL_BATTERY_FULL); - static lv_style_t styleIconBat; - lv_style_init(&styleIconBat); - lv_style_set_text_color(&styleIconBat, lv_color_hex(0x000000)); - lv_obj_add_style(statusbar_icon_bat, &styleIconBat, LV_PART_MAIN); - lv_obj_align(statusbar_icon_bat, LV_ALIGN_TOP_RIGHT, -5, 6); - - // Add WiFi icon to status bar - statusbar_icon_wifi = lv_label_create(lv_scr_act()); - lv_label_set_text(statusbar_icon_wifi, LV_SYMBOL_WIFI); - static lv_style_t styleIconWiFiStatusbar; - lv_style_init(&styleIconWiFiStatusbar); - lv_style_set_text_color(&styleIconWiFiStatusbar, lv_color_hex(0x000000)); - lv_obj_add_style(statusbar_icon_wifi, &styleIconWiFiStatusbar, LV_PART_MAIN); - lv_obj_align(statusbar_icon_wifi, LV_ALIGN_TOP_RIGHT, -30, 5); - - // Add Turtle icon to status bar - lv_obj_t *labelTurtleBar = lv_label_create(lv_scr_act()); - lv_label_set_text(labelTurtleBar, SYMBOL_TURTLE30PX); - static lv_style_t styleIconTurtleStatusbar; - lv_style_init(&styleIconTurtleStatusbar); - lv_style_set_text_color(&styleIconTurtleStatusbar, - lv_palette_main(LV_PALETTE_GREEN)); - lv_style_set_text_font(&styleIconTurtleStatusbar, &turtle_16); - lv_obj_add_style(labelTurtleBar, &styleIconTurtleStatusbar, LV_PART_MAIN); - lv_obj_align(labelTurtleBar, LV_ALIGN_TOP_LEFT, 5, 5); - - // Add a label to hold console text - // FUTURE TODO: Have 10px of overlap between the top console text and the - // status bar - terminalLabel = lv_label_create(lv_scr_act()); - lv_obj_align(terminalLabel, LV_ALIGN_BOTTOM_LEFT, 3, 0); - lv_obj_set_width(terminalLabel, 230); - lv_label_set_long_mode(terminalLabel, LV_LABEL_LONG_WRAP); - lv_style_init(&styleTerminalLabel); - lv_style_set_text_color(&styleTerminalLabel, lv_color_white()); - lv_obj_add_style(terminalLabel, &styleTerminalLabel, LV_PART_MAIN); - lv_label_set_text_static(terminalLabel, terminalTextBuffer); - lv_obj_move_background(terminalLabel); - - Serial.println("main app. screen built!"); - - _dispDriver->esp32_lvgl_release(); -} - -/**************************************************************************/ -/*! - @brief Add text on the terminal label and displays it. - @param text - Text to display on the terminal, should end in "\n" -*/ -/**************************************************************************/ -void ws_display_ui_helper::add_text_to_terminal(const char *text) { - Serial.println("add_text_to_terminal"); - char txtBuffer[256]; // temporary text buffer for snprintf - snprintf(txtBuffer, 256, text); - addToTerminal(txtBuffer); -} - -/**************************************************************************/ -/*! - @brief Adds a line of text on the terminal label and displays it. - @param text - A line of text to display on the terminal. - @note Reference: - https://github.com/lvgl/lv_demos/blob/release/v6/lv_apps/terminal/terminal.c -*/ -/**************************************************************************/ -void ws_display_ui_helper::addToTerminal(const char *txt_in) { - // Calculate text size - size_t txt_len = strlen(txt_in); - size_t old_len = strlen(terminalTextBuffer); - - // If the data is longer then the terminal ax size show the last part of data - if (txt_len > MAX_CONSOLE_TEXT_LEN) { - txt_in += (txt_len - MAX_CONSOLE_TEXT_LEN); - txt_len = MAX_CONSOLE_TEXT_LEN; - old_len = 0; - } - - // If the text become too long 'forget' the oldest lines - else if (old_len + txt_len > MAX_CONSOLE_TEXT_LEN) { - uint16_t new_start; - for (new_start = 0; new_start < old_len; new_start++) { - if (terminalTextBuffer[new_start] == '\n') { - if (new_start >= txt_len) { - while (terminalTextBuffer[new_start] == '\n' || - terminalTextBuffer[new_start] == '\r') - new_start++; - break; - } - } - } - - // If it wasn't able to make enough space on line breaks simply forget the - // oldest characters - if (new_start == old_len) { - new_start = old_len - (MAX_CONSOLE_TEXT_LEN - txt_len); - } - - // Move the remaining text to the beginning - uint16_t j; - for (j = new_start; j < old_len; j++) { - terminalTextBuffer[j - new_start] = terminalTextBuffer[j]; - } - old_len = old_len - new_start; - terminalTextBuffer[old_len] = '\0'; - } - - // Copy new text to the text buffer - memcpy(&terminalTextBuffer[old_len], txt_in, txt_len); - terminalTextBuffer[old_len + txt_len] = '\0'; - - // Update label - _dispDriver->esp32_lvgl_acquire(); - lv_label_set_text_static(terminalLabel, terminalTextBuffer); - _dispDriver->esp32_lvgl_release(); -} - -#endif \ No newline at end of file diff --git a/src/display/ws_display_ui_helper.h b/src/display/ws_display_ui_helper.h deleted file mode 100644 index 909d6c73a..000000000 --- a/src/display/ws_display_ui_helper.h +++ /dev/null @@ -1,91 +0,0 @@ -/*! - * @file ws_display_ui_helper.h - * - * LVGL UI Helper class for WipperSnapper - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2023 for Adafruit Industries. - * - * BSD license, all text here must be included in any redistribution. - * - */ - -#ifndef WS_DISPLAY_UI_HELPER_H -#define WS_DISPLAY_UI_HELPER_H - -#include "Wippersnapper.h" -#include "ws_display_driver.h" -#include "ws_display_tooltips.h" -#include - -/********************** - * MACROS - **********************/ -#define MAX_CONSOLE_TEXT_LEN 430 ///< Maximum text length on the console -/* External fonts and symbols */ -#define SYMBOL_CODE "\xEF\x87\x89" ///< Symbol code for file icon -#define SYMBOL_WIFI "\xEF\x87\xAB" ///< Symbol code for WiFi icon -#define SYMBOL_TURTLE30PX "\xEF\x9C\xA6" ///< Symbol code for turtle icon -#define SYMBOL_CLOUD "\xEF\x83\x82" ///< Symbol code for cloud icon -#define SYMBOL_ERROR_TRIANGLE \ - "\xEF\x81\xB1" ///< Symbol code for error triangle icon - -/********************** - * IMAGE DECLARE - **********************/ -LV_FONT_DECLARE(errorTriangle); ///< Error triangle icon -LV_FONT_DECLARE(file); ///< File icon -LV_FONT_DECLARE(wifi_30px); ///< WiFi icon -LV_FONT_DECLARE(cloud_30px); ///< Cloud icon -LV_FONT_DECLARE(turtle_30px); ///< Turtle icon -LV_FONT_DECLARE(turtle_16); ///< Turtle icon - -/// Icon names for use with set_load_bar_icon_complete() -enum loadBarIcons { - loadBarIconFile, ///< File icon - loadBarIconWifi, ///< WiFi icon - loadBarIconCloud, ///< Cloud icon - loadBarIconTurtle, ///< Turtle icon - loadBarIconCheckmark ///< Checkmark icon -}; - -class ws_display_driver; - -/**************************************************************************/ -/*! - @brief Helps build and manage the LVGL objects and screens for - the application code. -*/ -/**************************************************************************/ -class ws_display_ui_helper { -public: - /**************************************************************************/ - /*! - @brief Constructor for the ws_display_ui_helper class. - @param drv - Pointer to the display driver. - */ - /**************************************************************************/ - ws_display_ui_helper(ws_display_driver *drv) { _dispDriver = drv; }; - ~ws_display_ui_helper(){}; - - void set_bg_black(); - void show_scr_load(); - void clear_scr_load(); - void build_scr_monitor(); - void add_text_to_terminal(const char *text); - void set_load_bar_icon_complete(loadBarIcons iconType); - void set_label_status(const char *text); // callback ui help? - void remove_tip_timer(); - void show_scr_error(const char *lblError, const char *lblDesc); - bool getLoadingState(); - -private: - ws_display_driver *_dispDriver = nullptr; - void addToTerminal(const char *txt_in); - bool _loadingState = false; -}; -#endif // WS_DISPLAY_UI_HELPER_H diff --git a/src/provisioning/tinyusb/Wippersnapper_FS.cpp b/src/provisioning/tinyusb/Wippersnapper_FS.cpp index 658d8df46..355119fa1 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.cpp +++ b/src/provisioning/tinyusb/Wippersnapper_FS.cpp @@ -350,15 +350,7 @@ void Wippersnapper_FS::createSecretsFile() { secretsFile.flush(); secretsFile.close(); - writeToBootOut( - "ERROR: Please edit the secrets.json file. Then, reset your board.\n"); -#ifdef USE_DISPLAY - WS._ui_helper->show_scr_error( - "INVALID SETTINGS FILE", - "The settings.json file on the WIPPER drive contains default values. " - "Please edit it to reflect your Adafruit IO and network credentials. " - "When you're done, press RESET on the board."); -#endif + writeToBootOut("ERROR: Please edit the secrets.json file. Then, reset your board.\n"); // Re-attach the USB device for file access delay(500); initUSBMSC(); @@ -439,13 +431,7 @@ void Wippersnapper_FS::parseSecrets() { writeToBootOut( "ERROR: Invalid IO credentials in secrets.json! TO FIX: Please change " "io_username and io_key to match your Adafruit IO credentials!\n"); -#ifdef USE_DISPLAY - WS._ui_helper->show_scr_error( - "INVALID IO CREDS", - "The \"io_username/io_key\" fields within secrets.json are invalid, " - "please " - "change it to match your Adafruit IO credentials. Then, press RESET."); -#endif + fsHalt( "ERROR: Invalid IO credentials in secrets.json! TO FIX: Please change " "io_username and io_key to match your Adafruit IO credentials!"); @@ -456,13 +442,7 @@ void Wippersnapper_FS::parseSecrets() { writeToBootOut("ERROR: Invalid network credentials in secrets.json! TO " "FIX: Please change network_ssid and network_password to " "match your Adafruit IO credentials!\n"); -#ifdef USE_DISPLAY - WS._ui_helper->show_scr_error( - "INVALID NETWORK", - "The \"network_ssid and network_password\" fields within secrets.json " - "are invalid, please change it to match your WiFi credentials. Then, " - "press RESET."); -#endif + fsHalt("ERROR: Invalid network credentials in secrets.json! TO FIX: Please " "change network_ssid and network_password to match your Adafruit IO " "credentials!"); From f1a4e879b25333690852a8e6ae1eb93000b6dfa4 Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 3 Sep 2025 13:17:14 -0400 Subject: [PATCH 38/76] Remove LVGL from build tools --- .github/workflows/build-clang-doxy.yml | 20 +------------- platformio.ini | 38 -------------------------- 2 files changed, 1 insertion(+), 57 deletions(-) diff --git a/.github/workflows/build-clang-doxy.yml b/.github/workflows/build-clang-doxy.yml index 09b116d32..b29763a62 100644 --- a/.github/workflows/build-clang-doxy.yml +++ b/.github/workflows/build-clang-doxy.yml @@ -18,7 +18,7 @@ on: jobs: build-esp32sx-esptool: - name: 🏗️ESP32-Sx(lvgl) + name: 🏗️ESP32-Sx runs-on: ubuntu-latest strategy: fail-fast: false @@ -81,8 +81,6 @@ jobs: git clone --quiet https://github.com/adafruit/Adafruit-ST7735-Library.git /home/runner/Arduino/libraries/Adafruit-ST7735-Library git clone --quiet https://github.com/adafruit/Adafruit_TouchScreen.git /home/runner/Arduino/libraries/Adafruit_TouchScreen git clone --quiet https://github.com/adafruit/Adafruit_TinyUSB_Arduino /home/runner/Arduino/libraries/Adafruit_TinyUSB_Arduino - git clone --depth 1 --branch wippersnapper https://github.com/brentru/lvgl.git /home/runner/Arduino/libraries/lvgl - git clone --depth 1 --branch development https://github.com/brentru/Adafruit_LvGL_Glue.git /home/runner/Arduino/libraries/Adafruit_LittlevGL_Glue_Library - name: Download stable Nanopb id: download-nanopb continue-on-error: true @@ -112,12 +110,6 @@ jobs: # Copy files to WipperSnapper's src/nanopb directory cp nanopb/pb_common.* nanopb/pb_encode.* nanopb/pb_decode.* src/nanopb mv nanopb/pb.h src/nanopb/nanopb.pb.h - - name: List all files in Adafruit_LittlevGL_Glue_Library folder - run: | - ls /home/runner/Arduino/libraries/Adafruit_LittlevGL_Glue_Library - - name: Copy lv_conf.h file in Adafruit_LittlevGL_Glue_Library to the arduino library folder - run: | - cp /home/runner/Arduino/libraries/Adafruit_LittlevGL_Glue_Library/lv_conf.h /home/runner/Arduino/libraries - name: Install Dependencies (esptool) run: | pip3 install esptool @@ -292,8 +284,6 @@ jobs: git clone --quiet https://github.com/adafruit/Adafruit-ST7735-Library.git /home/runner/Arduino/libraries/Adafruit-ST7735-Library git clone --quiet https://github.com/adafruit/Adafruit_TouchScreen.git /home/runner/Arduino/libraries/Adafruit_TouchScreen git clone --quiet https://github.com/adafruit/Adafruit_TinyUSB_Arduino /home/runner/Arduino/libraries/Adafruit_TinyUSB_Arduino - git clone --depth 1 --branch wippersnapper https://github.com/brentru/lvgl.git /home/runner/Arduino/libraries/lvgl - git clone --depth 1 --branch development https://github.com/brentru/Adafruit_LvGL_Glue.git /home/runner/Arduino/libraries/Adafruit_LittlevGL_Glue_Library - name: Download stable Nanopb id: download-nanopb continue-on-error: true @@ -323,12 +313,6 @@ jobs: # Copy files to WipperSnapper's src/nanopb directory cp nanopb/pb_common.* nanopb/pb_encode.* nanopb/pb_decode.* src/nanopb mv nanopb/pb.h src/nanopb/nanopb.pb.h - - name: List all files in Adafruit_LittlevGL_Glue_Library folder - run: | - ls /home/runner/Arduino/libraries/Adafruit_LittlevGL_Glue_Library - - name: Copy lv_conf.h file in Adafruit_LittlevGL_Glue_Library to the arduino library folder - run: | - cp /home/runner/Arduino/libraries/Adafruit_LittlevGL_Glue_Library/lv_conf.h /home/runner/Arduino/libraries - name: Build for ESP32-SX run: | python3 ci/build_platform.py ${{ matrix.arduino-platform }} --build_timeout 48000 @@ -804,8 +788,6 @@ jobs: git clone --quiet https://github.com/adafruit/Adafruit-ST7735-Library.git /home/runner/Arduino/libraries/Adafruit-ST7735-Library git clone --quiet https://github.com/adafruit/Adafruit_TouchScreen.git /home/runner/Arduino/libraries/Adafruit_TouchScreen git clone --quiet https://github.com/adafruit/Adafruit_TinyUSB_Arduino /home/runner/Arduino/libraries/Adafruit_TinyUSB_Arduino - git clone --depth 1 --branch wippersnapper https://github.com/brentru/lvgl.git /home/runner/Arduino/libraries/lvgl - git clone --depth 1 --branch development https://github.com/brentru/Adafruit_LvGL_Glue.git /home/runner/Arduino/libraries/Adafruit_LittlevGL_Glue_Library - name: Download stable Nanopb id: download-nanopb continue-on-error: true diff --git a/platformio.ini b/platformio.ini index 1bbf6019d..f2e8b20ca 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,15 +16,6 @@ framework = arduino monitor_speed = 115200 lib_compat_mode = strict lib_deps = - ;;;;;;;;;;; FunHouse / LVGL Boards uncomment these ;;;;;;;;;;;;;; - ; https://github.com/adafruit/Adafruit_HX8357_Library.git - ; https://github.com/adafruit/Adafruit_ILI9341.git - ; https://github.com/adafruit/Adafruit_STMPE610.git - ; https://github.com/adafruit/Adafruit-ST7735-Library.git - ; https://github.com/adafruit/Adafruit_TouchScreen.git - ; https://github.com/brentru/lvgl.git#wippersnapper - ; https://github.com/brentru/Adafruit_LvGL_Glue.git#development - ;;;;;;;;;;; All Boards need these libraries included ;;;;;;;;;;;;;; adafruit/Adafruit Zero DMA Library adafruit/Adafruit NeoPixel adafruit/Adafruit SPIFlash @@ -296,35 +287,6 @@ build_flags = -DARDUINO_FUNHOUSE -DBOARD_HAS_PSRAM board_build.partitions = tinyuf2-partitions-4MB-noota.csv extra_scripts = pre:rename_usb_config.py -; Adafruit Funhouse ESP32-S2 -[env:adafruit_funhouse_esp32s2_debug] -extends = common:esp32 -board = adafruit_funhouse_esp32s2 -;lib_extra_dirs = -build_type = debug -build_flags = - -DARDUINO_FUNHOUSE - -DBOARD_HAS_PSRAM - -DCFG_TUSB_DEBUG=1 - -DDEBUG=1 - -DESP_LOG_LEVEL=ESP_LOG_VERBOSE - -DARDUINO_CORE_DEBUG_LEVEL=5 - -DCORE_DEBUG_LEVEL=5 - -DARDUHAL_LOG_LEVEL=5 - ; USB Configuration - ; Uncomment if USB CDC on boot is needed - ; -DARDUINO_USB_CDC_ON_BOOT=1 - ; -DARDUINO_USB_MODE=0 ; 0 for CDC + TinyUSB, 1 for Hardware CDC + JTAG - ; LVGL Debugging - -DLV_USE_DEBUG=1 - -DLV_USE_LOG=1 - -DLV_LOG_PRINTF=1 - -DLV_LOG_COLOR=1 - -DLV_LOG_LEVEL=LV_LOG_LEVEL_TRACE -;set partition to tinyuf2-partitions-4MB.csv as of idf 5.1 -board_build.partitions = tinyuf2-partitions-4MB-noota.csv -extra_scripts = pre:rename_usb_config.py - ; Adafruit QT Py ESP32 Pico [env:adafruit_qtpy_esp32] extends = common:esp32 From c3f38e663f48264622308b609b9815934ded2616 Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 3 Sep 2025 13:20:42 -0400 Subject: [PATCH 39/76] Fix CI for TFT --- .github/workflows/build-clang-doxy.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/build-clang-doxy.yml b/.github/workflows/build-clang-doxy.yml index 94ed67e4b..ea8af19c8 100644 --- a/.github/workflows/build-clang-doxy.yml +++ b/.github/workflows/build-clang-doxy.yml @@ -876,12 +876,6 @@ jobs: # Copy files to WipperSnapper's src/nanopb directory cp nanopb/pb_common.* nanopb/pb_encode.* nanopb/pb_decode.* src/nanopb mv nanopb/pb.h src/nanopb/nanopb.pb.h - - name: List all files in Adafruit_LittlevGL_Glue_Library folder - run: | - ls /home/runner/Arduino/libraries/Adafruit_LittlevGL_Glue_Library - - name: Copy lv_conf.h file in Adafruit_LittlevGL_Glue_Library to the arduino library folder - run: | - cp /home/runner/Arduino/libraries/Adafruit_LittlevGL_Glue_Library/lv_conf.h /home/runner/Arduino/libraries - name: Build for ESP32-SX run: python3 ci/build_platform.py ${{ matrix.arduino-platform }} --build_timeout 48000 - name: list From 0aea2c007f2a223a73d8697666c8eb1de0b01010 Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 3 Sep 2025 13:27:04 -0400 Subject: [PATCH 40/76] Add Adafruit AS5600 Library --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 22fde18e1..ee7ec04f0 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper category=Communication url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino architectures=* -depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library \ No newline at end of file +depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library, Adafruit AS5600 Library \ No newline at end of file From cc42fbb79cdc3d211cb8877829097e35fd1e7aef Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 3 Sep 2025 13:38:55 -0400 Subject: [PATCH 41/76] Add Adafruit BMP5xx Library --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index ee7ec04f0..9e4f40f18 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper category=Communication url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino architectures=* -depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library, Adafruit AS5600 Library \ No newline at end of file +depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library, Adafruit AS5600 Library, Adafruit BMP5xx Library \ No newline at end of file From 49967801ea96384fbefdf8af000671be5bf603f3 Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 3 Sep 2025 13:50:21 -0400 Subject: [PATCH 42/76] Add Adafruit MLX90632 Library --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 9e4f40f18..5f03ff7fe 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper category=Communication url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino architectures=* -depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library, Adafruit AS5600 Library, Adafruit BMP5xx Library \ No newline at end of file +depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library, Adafruit AS5600 Library, Adafruit BMP5xx Library, Adafruit MLX90632 Library \ No newline at end of file From bfb1d3a8e65477bf951869e93eb8409a1d5ec143 Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 3 Sep 2025 14:33:09 -0400 Subject: [PATCH 43/76] Clang ST7789 --- src/components/display/drivers/dispDrvSt7789.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index 58250fd7c..ae5428548 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -58,18 +58,18 @@ class dispDrvSt7789 : public dispDrvBase { bool begin() override { // Special power control configuration for -// boards with built-in TFTs +// boards with built-in TFTs #if defined(TFT_BACKLITE) // turn on backlite pinMode(TFT_BACKLITE, OUTPUT); digitalWrite(TFT_BACKLITE, HIGH); - #if defined(TFT_I2C_POWER) +#if defined(TFT_I2C_POWER) // turn on the TFT / I2C power supply pinMode(TFT_I2C_POWER, OUTPUT); digitalWrite(TFT_I2C_POWER, HIGH); delay(10); - #endif // TFT_I2C_POWER +#endif // TFT_I2C_POWER #endif _display = new Adafruit_ST7789(_pin_cs, _pin_dc, _pin_rst); From 8022eddd9c1baf5e534cecbdea9e233849b13cc2 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 4 Sep 2025 11:37:10 -0400 Subject: [PATCH 44/76] Add preemptive driver for ssd1306, no refactoring yet --- src/components/display/drivers/dispDrvBase.h | 14 ++ .../display/drivers/dispDrvSsd1306.h | 146 ++++++++++++++++++ src/components/display/hardware.h | 1 + 3 files changed, 161 insertions(+) create mode 100644 src/components/display/drivers/dispDrvSsd1306.h diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index d74c2d733..ead3a3f19 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -63,6 +63,18 @@ class dispDrvBase { : _pin_cs(cs), _pin_dc(dc), _pin_mosi(mosi), _pin_sck(sck), _pin_rst(rst), _pin_miso(miso) {} + + /*! + @brief Creates a new I2C output component driver. + @param i2c + The I2C hardware interface, default is Wire. + @param sensorAddress + The I2C sensor's unique address. + */ + dispDrvBase(TwoWire *i2c, uint16_t sensorAddress) { + // No-op constructor + } + /*! @brief Destructor for the base display driver. This destructor is virtual to allow derived classes to clean up @@ -133,6 +145,8 @@ class dispDrvBase { uint16_t _pin_mosi; ///< Optional MOSI pin for SPI TFT displays uint16_t _pin_miso; ///< Optional MISO pin for SPI TFT displays uint16_t _pin_sck; ///< Optional SCK pin for SPI TFT displays + TwoWire *_i2c; ///< Optional pointer to the I2C driver's Wire object + uint16_t _sensorAddress; ///< Optional I2C sensor address uint8_t _text_sz = 1; ///< Text size for displaying a message int16_t _height; ///< Height of the display int16_t _width; ///< Width of the display diff --git a/src/components/display/drivers/dispDrvSsd1306.h b/src/components/display/drivers/dispDrvSsd1306.h new file mode 100644 index 000000000..d5df9297a --- /dev/null +++ b/src/components/display/drivers/dispDrvSsd1306.h @@ -0,0 +1,146 @@ +/*! + * @file src/components/display/drivers/dispDrvSsd1306.h + * + * Driver for SSD1306-based OLED displays. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DISP_DRV_SSD1306 +#define WS_DISP_DRV_SSD1306 + +#include "dispDrvBase.h" +#include +#include + +#define WS_SSD1306_DEFAULT_WIDTH \ + 128 ///< Default width for a ssd1306 128x64 display +#define WS_SSD1306_DEFAULT_HEIGHT \ + 64 ///< Default height for a ssd1306 128x64 display + + +/*! + @brief Driver for SSD1306-based TFT displays. +*/ +class dispDrvSsd1306 : public dispDrvBase { +public: + /*! + @brief Constructor for the SSD1306 display driver. + */ + dispDrvSsd1306(TwoWire *i2c, uint16_t sensorAddress) : dispDrvBase(i2c, sensorAddress), _display(nullptr) { + _i2c = i2c; + _sensorAddress = sensorAddress; + _width = WS_SSD1306_DEFAULT_WIDTH; + _height = WS_SSD1306_DEFAULT_HEIGHT; + } + + ~dispDrvSsd1306() { + if (_display) { + _display->clearDisplay(); + _display->display(); + _display->ssd1306_command(SSD1306_DISPLAYOFF); + delete _display; + _display = nullptr; + } + } + + /*! + @brief Attempts to initialize the SSD1306 display driver. + @return True if the display was initialized successfully, false otherwise. + */ + bool begin() override { + if (_i2c == nullptr) + return false; + // Attempt to create and allocate a SSD1306 obj. + _display = new Adafruit_SSD1306(_width, _height, _i2c); + if (!_display->begin(SSD1306_SWITCHCAPVCC, _sensorAddress)) + return false; + // Configure the rotation, text size and color + _display->setRotation(_rotation); + _display->setTextSize(_text_sz); + _display->setTextColor(SSD1306_WHITE); + // Use full 256 char 'Code Page 437' font + _display->cp437(true); + // Clear the buffer + _display->clearDisplay(); + _display->display(); + return true; + } + + /*! + @brief Sets the text size for the display. + @param s + The text size to set. + @note This method overrides the base class method to provide specific + functionality for the SSD1306 driver. + */ + void setTextSize(uint8_t s) override { + if (!_display) + return; + _text_sz = s; + _display->setTextSize(s); + } + + /*! + @brief Writes a message to the display. + @param message + The message to write to the display. + @note This method overrides the base class method to provide specific + functionality for the SSD1306 driver. + */ + virtual void writeMessage(const char *message) override { + if (_display == nullptr) + return; + + // Start with a fresh display buffer + // and settings + int16_t y_idx = 0; + _display->clearDisplay(); + _display->setTextSize(_text_sz); + _display->setTextColor(SSD1306_WHITE); + _display->setCursor(0, y_idx); + _display->display(); + + // Calculate the line height based on the text size (NOTE: base height is + // 8px) + int16_t line_height = 8 * _text_sz; + uint16_t c_idx = 0; + size_t msg_size = strlen(message); + for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) { + if (message[i] == '\\' && i + 1 < msg_size && + (message[i + 1] == 'n' || message[i + 1] == 'r')) { + // Handle \r\n sequence as a single newline + if (message[i + 1] == 'r' && i + 3 < msg_size && + message[i + 2] == '\\' && message[i + 3] == 'n') { + // Skip to the next line + y_idx += line_height; + _display->setCursor(0, y_idx); + i += 3; + } else if (message[i + 1] == 'n') { + // Skip to the next line + y_idx += line_height; + _display->setCursor(0, y_idx); + i++; + } + } else if (message[i] == 0xC2 && message[i + 1] == 0xB0) { + _display->write(char(248)); + _display->display(); + i++; + } else { + _display->print(message[i]); + _display->display(); + } + } +} + +private: + Adafruit_SSD1306 *_display; +}; + +#endif // WS_DISP_DRV_SSD1306 \ No newline at end of file diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 9446f1467..9e16d6d0d 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -43,6 +43,7 @@ class DisplayHardware { wippersnapper_display_v1_EpdSpiConfig *spi_config); bool beginTft(wippersnapper_display_v1_TftConfig *config, wippersnapper_display_v1_TftSpiConfig *spi_config); + // TODO: bool beginOled(...); // // API for Adafruit_GFX that abstracts hardware functionality From 6a233fb2a0a4ced6cd219578d7d81ff327117cee Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 4 Sep 2025 14:54:46 -0400 Subject: [PATCH 45/76] Refactor out i2c_output work, bring in new display elements as i2c outputs! --- src/Wippersnapper.cpp | 19 -- src/components/display/controller.cpp | 19 +- src/components/display/hardware.cpp | 69 ++++- src/components/display/hardware.h | 8 +- src/components/i2c/WipperSnapper_I2C.cpp | 263 ------------------ src/components/i2c/WipperSnapper_I2C.h | 21 +- .../drivers/WipperSnapper_I2C_Driver_Out.h | 145 ---------- .../WipperSnapper_I2C_Driver_Out_7Seg.h | 209 -------------- .../WipperSnapper_I2C_Driver_Out_CharLcd.h | 163 ----------- ...ipperSnapper_I2C_Driver_Out_QuadAlphaNum.h | 178 ------------ .../WipperSnapper_I2C_Driver_Out_Sh1107.h | 208 -------------- .../WipperSnapper_I2C_Driver_Out_Ssd1306.h | 166 ----------- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 21 +- src/wippersnapper/display/v1/display.pb.h | 208 +++++++++----- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 28 +- src/wippersnapper/i2c/v1/i2c.pb.h | 223 +-------------- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 10 +- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 32 files changed, 281 insertions(+), 1707 deletions(-) delete mode 100644 src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out.h delete mode 100644 src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_7Seg.h delete mode 100644 src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_CharLcd.h delete mode 100644 src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h delete mode 100644 src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Sh1107.h delete mode 100644 src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Ssd1306.h diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index cb9ff1898..9f8662329 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -834,25 +834,6 @@ bool cbDecodeSignalRequestI2C(pb_istream_t *stream, const pb_field_t *field, if (!encodeI2CResponse(&msgi2cResponse)) { return false; } - } else if (field->tag == - wippersnapper_signal_v1_I2CRequest_req_i2c_device_out_write_tag) { - WS_DEBUG_PRINTLN("[app] I2C Device Output Write"); - // Decode stream into an I2CDeviceDeinitRequest - wippersnapper_i2c_v1_I2CDeviceOutputWrite msgDeviceWrite = - wippersnapper_i2c_v1_I2CDeviceOutputWrite_init_zero; - // Decode stream into struct, msgI2CDeviceDeinitRequest - if (!ws_pb_decode(stream, wippersnapper_i2c_v1_I2CDeviceOutputWrite_fields, - &msgDeviceWrite)) { - WS_DEBUG_PRINTLN( - "[app] ERROR: Failed decoding I2CDeviceOutputWrite message."); - return false; - } - - if (!WS._i2cPort0->Handle_I2cDeviceOutputWrite(&msgDeviceWrite)) { - WS_DEBUG_PRINTLN("[app] ERROR: Failed to write to I2C output device."); - return false; // fail out if we can't decode, we don't have a response to - // publish - } WS_DEBUG_PRINTLN("[app] I2C Device Output Write Done"); return true; // we successfully wrote to the device, this subtype has no // response to publish to IO diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 709ef8a4f..67c0ad975 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -51,11 +51,26 @@ bool DisplayController::Handle_Display_AddOrReplace( if (msgAdd->which_config == wippersnapper_display_v1_DisplayAddOrReplace_config_epd_tag) { did_begin = display->beginEPD(&msgAdd->config.config_epd, - &msgAdd->interface_type.spi_epd); + &msgAdd->interface_type.cfg_spi); } else if (msgAdd->which_config == wippersnapper_display_v1_DisplayAddOrReplace_config_tft_tag) { did_begin = display->beginTft(&msgAdd->config.config_tft, - &msgAdd->interface_type.spi_tft); + &msgAdd->interface_type.cfg_spi); + } else if (msgAdd->which_config == + wippersnapper_display_v1_DisplayAddOrReplace_config_ssd1306_tag) { + did_begin = display->beginOled(&msgAdd->config.config_ssd1306, + &msgAdd->interface_type.cfg_i2c); + } else if ( + msgAdd->which_config == + wippersnapper_display_v1_DisplayAddOrReplace_config_led_backpack_tag) { + WS_DEBUG_PRINTLN("[display] LED Backpack support coming soon!"); + delete display; + return false; + } else if (msgAdd->which_config == + wippersnapper_display_v1_DisplayAddOrReplace_config_char_lcd_tag) { + WS_DEBUG_PRINTLN("[display] Character LCD support coming soon!"); + delete display; + return false; } else { WS_DEBUG_PRINTLN("[display] Unsupported display configuration type!"); delete display; diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 798932f99..c1d4ad79d 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -173,9 +173,8 @@ int16_t DisplayHardware::parsePin(const char *pinStr) { Pointer to the SPI configuration structure for EPD. @return True if configuration was successful, False otherwise. */ -bool DisplayHardware::beginEPD( - wippersnapper_display_v1_EPDConfig *config, - wippersnapper_display_v1_EpdSpiConfig *spi_config) { +bool DisplayHardware::beginEPD(wippersnapper_display_v1_EPDConfig *config, + wippersnapper_display_v1_SpiConfig *spi_config) { // Validate pointers if (config == nullptr || spi_config == nullptr) { WS_DEBUG_PRINTLN("[display] EPD config or SPI config is null!"); @@ -273,9 +272,8 @@ void DisplayHardware::removeSuffix(const char *suffix) { Pointer to the SPI configuration structure for TFT. @return True if configuration was successful, False otherwise. */ -bool DisplayHardware::beginTft( - wippersnapper_display_v1_TftConfig *config, - wippersnapper_display_v1_TftSpiConfig *spi_config) { +bool DisplayHardware::beginTft(wippersnapper_display_v1_TftConfig *config, + wippersnapper_display_v1_SpiConfig *spi_config) { // Validate pointers if (config == nullptr || spi_config == nullptr) { WS_DEBUG_PRINTLN("[display] EPD config or SPI config is null!"); @@ -333,6 +331,65 @@ bool DisplayHardware::beginTft( return true; } +/*! + @brief Attempts to configure and initialize an OLED display + @param config + Pointer to the OLED's configuration structure. + @param i2c_config + Pointer to the I2C configuration structure for OLED. + @return True if configuration was successful, False otherwise. +*/ +bool DisplayHardware::beginOled( + wippersnapper_display_v1_SSD1306Config *config, + wippersnapper_display_v1_I2cConfig *i2c_config) { + // Validate pointers + if (config == nullptr || i2c_config == nullptr || !i2c_config->has_i2c) { + WS_DEBUG_PRINTLN("[display] OLED or I2C config is null!"); + return false; + } + + // If we already have a display driver assigned to this hardware instance, + // clean it up! + if (_drvDisp) { + delete _drvDisp; + _drvDisp = nullptr; + } + + if (strnlen(i2c_config->i2c.i2c_device_name, + sizeof(i2c_config->i2c.i2c_device_name)) < + sizeof(i2c_config->i2c.i2c_device_name) && + strcmp(i2c_config->i2c.i2c_device_name, "SSD1306") == 0) { + _drvDisp = new dispDrvSsd1306(WS._i2cPort0->getBus(), + i2c_config->i2c.i2c_device_address); + } else { + WS_DEBUG_PRINTLN("[display] Unsupported OLED driver!"); + return false; + } + + // Validate that the display driver was created successfully + if (!_drvDisp) { + WS_DEBUG_PRINTLN("[display] Failed to create display driver!"); + _drvDisp = nullptr; + return false; + } + + // Configure display dimensions and text size + _drvDisp->setWidth(config->width); + _drvDisp->setHeight(config->height); + // tODO: Remove the ssd-1306 -specic text size setters + // _drvDisp->setTextSize(config->text_size); + + // Initialize the display driver + if (!_drvDisp->begin()) { + WS_DEBUG_PRINTLN("[display] Failed to begin display driver!"); + delete _drvDisp; + _drvDisp = nullptr; + return false; + } + + return true; +} + /*! @brief Gets the name of the display hardware instance. @return The name of the display hardware instance. diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 9e16d6d0d..42bb3ce72 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -16,6 +16,7 @@ #define WS_DISPLAY_HARDWARE_H #include "Wippersnapper.h" #include "drivers/dispDrvBase.h" +#include "drivers/dispDrvSsd1306.h" #include "drivers/dispDrvSt7789.h" #include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h" #include "drivers/dispDrvThinkInkGrayscale4T5.h" @@ -40,10 +41,11 @@ class DisplayHardware { void setType(wippersnapper_display_v1_DisplayType type); wippersnapper_display_v1_DisplayType getType(); bool beginEPD(wippersnapper_display_v1_EPDConfig *config, - wippersnapper_display_v1_EpdSpiConfig *spi_config); + wippersnapper_display_v1_SpiConfig *spi_config); bool beginTft(wippersnapper_display_v1_TftConfig *config, - wippersnapper_display_v1_TftSpiConfig *spi_config); - // TODO: bool beginOled(...); + wippersnapper_display_v1_SpiConfig *spi_config); + bool beginOled(wippersnapper_display_v1_SSD1306Config *config, + wippersnapper_display_v1_I2cConfig *i2c_config); // // API for Adafruit_GFX that abstracts hardware functionality diff --git a/src/components/i2c/WipperSnapper_I2C.cpp b/src/components/i2c/WipperSnapper_I2C.cpp index 2947702c2..f59240833 100644 --- a/src/components/i2c/WipperSnapper_I2C.cpp +++ b/src/components/i2c/WipperSnapper_I2C.cpp @@ -932,105 +932,6 @@ bool WipperSnapper_Component_I2C::initI2CDevice( _adt7410->configureDriver(msgDeviceInitReq); drivers.push_back(_adt7410); WS_DEBUG_PRINTLN("ADT7410 Initialized Successfully!"); - } else if (strcmp("quadalphanum", msgDeviceInitReq->i2c_device_name) == 0) { - _quadAlphaNum = - new WipperSnapper_I2C_Driver_Out_QuadAlphaNum(this->_i2c, i2cAddress); - _quadAlphaNum->ConfigureI2CBackpack( - msgDeviceInitReq->i2c_output_add.config.led_backpack_config.brightness, - msgDeviceInitReq->i2c_output_add.config.led_backpack_config.alignment); - if (!_quadAlphaNum->begin()) { - WS_DEBUG_PRINTLN("ERROR: Failed to initialize Quad Alphanum. Display!"); - _busStatusResponse = - wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL; - return false; - } - _drivers_out.push_back(_quadAlphaNum); - WS_DEBUG_PRINTLN("Quad Alphanum. Display Initialized Successfully!"); - } else if (strcmp("chardisplay16x2", msgDeviceInitReq->i2c_device_name) == - 0 || - strcmp("chardisplay20x4", msgDeviceInitReq->i2c_device_name) == - 0) { - _charLcd = new WipperSnapper_I2C_Driver_Out_CharLcd(this->_i2c, i2cAddress); - _charLcd->ConfigureCharLcd( - msgDeviceInitReq->i2c_output_add.config.char_lcd_config.rows, - msgDeviceInitReq->i2c_output_add.config.char_lcd_config.columns); - if (!_charLcd->begin()) { - WS_DEBUG_PRINTLN("ERROR: Failed to initialize Character LCD!"); - _busStatusResponse = - wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL; - return false; - } - _drivers_out.push_back(_charLcd); - WS_DEBUG_PRINTLN("Char LCD Display Initialized Successfully!"); - } else if (strcmp("7seg", msgDeviceInitReq->i2c_device_name) == 0) { - _sevenSeg = new WipperSnapper_I2C_Driver_Out_7Seg(this->_i2c, i2cAddress); - _sevenSeg->ConfigureI2CBackpack( - msgDeviceInitReq->i2c_output_add.config.led_backpack_config.brightness, - msgDeviceInitReq->i2c_output_add.config.led_backpack_config.alignment); - if (!_sevenSeg->begin()) { - WS_DEBUG_PRINTLN("ERROR: Failed to initialize 7-Segement LED Matrix!"); - _busStatusResponse = - wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL; - return false; - } - _drivers_out.push_back(_sevenSeg); - WS_DEBUG_PRINTLN("7-Segement LED Matrix Initialized Successfully!"); - } else if (strcmp("fthrwingoled128x64", msgDeviceInitReq->i2c_device_name) == - 0 || - strcmp("fthrwingoled128x64lg", - msgDeviceInitReq->i2c_device_name) == 0) { - WS_DEBUG_PRINTLN("SH1107 display detected!"); - _sh1107 = new WipperSnapper_I2C_Driver_Out_SH1107(this->_i2c, i2cAddress); - WS_DEBUG_PRINTLN("Configuring SH1107 display..."); - _sh1107->ConfigureSH1107( - (uint8_t)msgDeviceInitReq->i2c_output_add.config.ssd1306_config.width, - (uint8_t)msgDeviceInitReq->i2c_output_add.config.ssd1306_config.height, - (uint8_t) - msgDeviceInitReq->i2c_output_add.config.ssd1306_config.text_size, - OLED_128X64_WING_ROTATION_90); // fixed as currently the only screen is - // 128x64wing (needs a rotation of 1 / 90degrees and constructor w/h swap). - if (!_sh1107->begin()) { - WS_DEBUG_PRINTLN("ERROR: Failed to initialize sh1107!"); - _busStatusResponse = - wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL; - return false; - } - WS_DEBUG_PRINTLN("SH1107 display configured successfully!"); - _drivers_out.push_back(_sh1107); - WS_DEBUG_PRINTLN("SH1107 display initialized Successfully!"); - } else if (strcmp("oled32x64large", msgDeviceInitReq->i2c_device_name) == 0 || - strcmp("oled64x32default", msgDeviceInitReq->i2c_device_name) == - 0 || - strcmp("oled64x32large", msgDeviceInitReq->i2c_device_name) == 0 || - strcmp("fthrwingoled128x32", msgDeviceInitReq->i2c_device_name) == - 0 || - strcmp("fthrwingoled128x32lg", - msgDeviceInitReq->i2c_device_name) == 0 || - strcmp("oled128x32default", msgDeviceInitReq->i2c_device_name) == - 0 || - strcmp("oled128x32large", msgDeviceInitReq->i2c_device_name) == - 0 || - strcmp("oled128x64default", msgDeviceInitReq->i2c_device_name) == - 0 || - strcmp("oled128x64large", msgDeviceInitReq->i2c_device_name) == - 0) { - WS_DEBUG_PRINTLN("SSD1306 display detected!"); - _ssd1306 = new WipperSnapper_I2C_Driver_Out_Ssd1306(this->_i2c, i2cAddress); - WS_DEBUG_PRINTLN("Configuring SSD1306 display..."); - _ssd1306->ConfigureSSD1306( - (uint8_t)msgDeviceInitReq->i2c_output_add.config.ssd1306_config.width, - (uint8_t)msgDeviceInitReq->i2c_output_add.config.ssd1306_config.height, - (uint8_t) - msgDeviceInitReq->i2c_output_add.config.ssd1306_config.text_size); - if (!_ssd1306->begin()) { - WS_DEBUG_PRINTLN("ERROR: Failed to initialize ssd1306!"); - _busStatusResponse = - wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL; - return false; - } - WS_DEBUG_PRINTLN("SSD1306 display configured successfully!"); - _drivers_out.push_back(_ssd1306); - WS_DEBUG_PRINTLN("SSD1306 display initialized Successfully!"); } else { WS_DEBUG_PRINTLN("ERROR: I2C device type not found!") _busStatusResponse = @@ -1100,27 +1001,6 @@ void WipperSnapper_Component_I2C::deinitI2CDevice( } } - // Check for output drivers - std::vector::iterator out_iter, out_end; - for (out_iter = _drivers_out.begin(), out_end = _drivers_out.end(); - out_iter != out_end; ++out_iter) { - if ((*out_iter)->getI2CAddress() == deviceAddr) { - // Set the driver to nullptr - *out_iter = nullptr; -// ESP-IDF, Erase–remove iter ptr from driver vector -#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) - *out_iter = nullptr; - _drivers_out.erase( - remove(_drivers_out.begin(), _drivers_out.end(), nullptr), - _drivers_out.end()); -#else - // Arduino can not erase-remove, erase only - _drivers_out.erase(out_iter); -#endif - WS_DEBUG_PRINTLN("I2C Device De-initialized!"); - } - } - _busStatusResponse = wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_SUCCESS; } @@ -1190,147 +1070,6 @@ void WipperSnapper_Component_I2C::fillEventMessage( msgi2cResponse->payload.resp_i2c_device_event.sensor_event_count++; } -/*******************************************************************************/ -/*! - @brief Displays a sensor event message on the TFT - @param msgi2cResponse - A pointer to an I2CResponse message. - @param sensorAddress - The unique I2C address of the sensor. -*/ -/*******************************************************************************/ -void WipperSnapper_Component_I2C::displayDeviceEventMessage( - wippersnapper_signal_v1_I2CResponse *msgi2cResponse, - uint32_t sensorAddress) { - - pb_size_t numEvents = - msgi2cResponse->payload.resp_i2c_device_event.sensor_event_count; - - char buffer[100]; - for (int i = 0; i < numEvents; i++) { - float value = - msgi2cResponse->payload.resp_i2c_device_event.sensor_event[i].value; - - switch ( - msgi2cResponse->payload.resp_i2c_device_event.sensor_event[i].type) { - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE: - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE: - snprintf(buffer, 100, "[I2C: %#x] Read: %0.3f *C\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT: - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE_FAHRENHEIT: - snprintf(buffer, 100, "[I2C: %#x] Read: %0.3f *F\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY: - snprintf(buffer, 100, "[I2C: %#x] Read: %0.3f %% rh\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_PRESSURE: - snprintf(buffer, 100, "[I2C: %#x] Read: %0.3f hPA\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_ALTITUDE: - snprintf(buffer, 100, "[I2C: %x] Read: %0.3f m\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_LIGHT: - snprintf(buffer, 100, "[I2C: %x] Read: %0.3f lux\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_PM10_STD: - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_PM25_STD: - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_PM100_STD: - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_CO2: - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_ECO2: - snprintf(buffer, 100, "[I2C: %x] Read: %0.3f ppm\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_TVOC: - snprintf(buffer, 100, "[I2C: %x] Read: %0.3f ppb\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_UNITLESS_PERCENT: - snprintf(buffer, 100, "[I2C: %x] Read: %0.3f%%\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_VOLTAGE: - snprintf(buffer, 100, "[I2C: %x] Read: %0.3f V\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_CURRENT: - snprintf(buffer, 100, "[I2C: %x] Read: %0.3f mA\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_RAW: - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_PROXIMITY: - snprintf(buffer, 100, "[I2C: %x] Read: %0.3f\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_GAS_RESISTANCE: - snprintf(buffer, 100, "[I2C: %x] Read: %0.3f Ohms\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_NOX_INDEX: - snprintf(buffer, 100, "[I2C: %x] Read: %0.3f NOX\n", - (unsigned int)sensorAddress, value); - break; - case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_VOC_INDEX: - snprintf(buffer, 100, "[I2C: %x] Read: %0.3f VOC\n", - (unsigned int)sensorAddress, value); - break; - default: - break; - } - } -} - -/*******************************************************************************/ -/*! - @brief Handles an I2CDeviceOutputWrite message. - @param msgDeviceWrite - A decoded I2CDeviceOutputWrite message. - @returns True if the message was handled successfully, false otherwise. -*/ -/*******************************************************************************/ -bool WipperSnapper_Component_I2C::Handle_I2cDeviceOutputWrite( - wippersnapper_i2c_v1_I2CDeviceOutputWrite *msgDeviceWrite) { - - // Create a ptr to the base driver out - WipperSnapper_I2C_Driver_Out *driver_out = nullptr; - // Find the matching driver by address in the _drivers_out vector - for (size_t i = 0; i < _drivers_out.size(); i++) { - if (_drivers_out[i]->getI2CAddress() == - msgDeviceWrite->i2c_device_address) { - driver_out = _drivers_out[i]; - break; - } - } - if (driver_out == nullptr) { - WS_DEBUG_PRINTLN("ERROR: I2c output driver not found within drivers_out!"); - return false; - } - - // Call the output_msg - if (msgDeviceWrite->which_output_msg == - wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_led_backpack_tag) { - driver_out->WriteLedBackpack( - &msgDeviceWrite->output_msg.write_led_backpack); - } else if (msgDeviceWrite->which_output_msg == - wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_char_lcd_tag) { - driver_out->WriteMessageCharLCD(&msgDeviceWrite->output_msg.write_char_lcd); - } else if (msgDeviceWrite->which_output_msg == - wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_ssd1306_tag) { - driver_out->WriteMessageSSD1306( - msgDeviceWrite->output_msg.write_ssd1306.message); - } else { - WS_DEBUG_PRINTLN("ERROR: Unknown i2c output message type!"); - return false; - } - return true; -} - /*******************************************************************************/ /*! @brief Queries all I2C device drivers for new values. Fills and sends an @@ -1592,8 +1331,6 @@ void WipperSnapper_Component_I2C::update() { continue; } - displayDeviceEventMessage(&msgi2cResponse, (*iter)->getI2CAddress()); - // Encode and publish I2CDeviceEvent message if (!encodePublishI2CDeviceEventMsg(&msgi2cResponse, (*iter)->getI2CAddress())) { diff --git a/src/components/i2c/WipperSnapper_I2C.h b/src/components/i2c/WipperSnapper_I2C.h index a83765370..b858c8ff3 100644 --- a/src/components/i2c/WipperSnapper_I2C.h +++ b/src/components/i2c/WipperSnapper_I2C.h @@ -57,12 +57,6 @@ #include "drivers/WipperSnapper_I2C_Driver_MPRLS.h" #include "drivers/WipperSnapper_I2C_Driver_MS8607.h" #include "drivers/WipperSnapper_I2C_Driver_NAU7802.h" -#include "drivers/WipperSnapper_I2C_Driver_Out.h" -#include "drivers/WipperSnapper_I2C_Driver_Out_7Seg.h" -#include "drivers/WipperSnapper_I2C_Driver_Out_CharLcd.h" -#include "drivers/WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h" -#include "drivers/WipperSnapper_I2C_Driver_Out_Sh1107.h" -#include "drivers/WipperSnapper_I2C_Driver_Out_Ssd1306.h" #include "drivers/WipperSnapper_I2C_Driver_PCT2075.h" #include "drivers/WipperSnapper_I2C_Driver_PM25.h" #include "drivers/WipperSnapper_I2C_Driver_SCD30.h" @@ -113,6 +107,7 @@ class WipperSnapper_Component_I2C { wippersnapper_i2c_v1_I2CBusScanResponse scanAddresses(); bool initI2CDevice(wippersnapper_i2c_v1_I2CDeviceInitRequest *msgDeviceInitReq); + TwoWire *getBus() { return _i2c; } void updateI2CDeviceProperties( wippersnapper_i2c_v1_I2CDeviceUpdateRequest *msgDeviceUpdateReq); @@ -121,9 +116,6 @@ class WipperSnapper_Component_I2C { void update(); - bool Handle_I2cDeviceOutputWrite( - wippersnapper_i2c_v1_I2CDeviceOutputWrite *msgDeviceWrite); - void sensorEventRead( std::vector::iterator &iter, unsigned long curTime, @@ -141,10 +133,6 @@ class WipperSnapper_Component_I2C { float value, wippersnapper_i2c_v1_SensorType sensorType); - void - displayDeviceEventMessage(wippersnapper_signal_v1_I2CResponse *msgi2cResponse, - uint32_t sensorAddress); - bool encodePublishI2CDeviceEventMsg( wippersnapper_signal_v1_I2CResponse *msgi2cResponse, uint32_t sensorAddress); @@ -156,8 +144,6 @@ class WipperSnapper_Component_I2C { wippersnapper_i2c_v1_BusResponse _busStatusResponse; std::vector drivers; ///< List of i2c sensor drivers - std::vector - _drivers_out; ///< List of i2c output drivers // Sensor driver objects WipperSnapper_I2C_Driver_AHTX0 *_ahtx0 = nullptr; WipperSnapper_I2C_Driver_AS5600 *_as5600 = nullptr; @@ -221,11 +207,6 @@ class WipperSnapper_Component_I2C { WipperSnapper_I2C_Driver_VL6180X *_vl6180x = nullptr; WipperSnapper_I2C_Driver_MAX17048 *_max17048 = nullptr; WipperSnapper_I2C_Driver_ADT7410 *_adt7410 = nullptr; - WipperSnapper_I2C_Driver_Out_QuadAlphaNum *_quadAlphaNum = nullptr; - WipperSnapper_I2C_Driver_Out_CharLcd *_charLcd = nullptr; - WipperSnapper_I2C_Driver_Out_7Seg *_sevenSeg = nullptr; - WipperSnapper_I2C_Driver_Out_SH1107 *_sh1107 = nullptr; - WipperSnapper_I2C_Driver_Out_Ssd1306 *_ssd1306 = nullptr; }; extern Wippersnapper WS; diff --git a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out.h deleted file mode 100644 index c92debec7..000000000 --- a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out.h +++ /dev/null @@ -1,145 +0,0 @@ -/*! - * @file WipperSnapper_I2C_Driver_Out.h - * - * Derived class for I2C output driver components - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell 2025 for Adafruit Industries. - * - * MIT license, all text here must be included in any redistribution. - * - */ - -#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_H -#define WIPPERSNAPPER_I2C_DRIVER_OUT_H - -#include "WipperSnapper_I2C_Driver.h" -#include - -/*! - @brief Derived class for I2C output component drivers. -*/ -class WipperSnapper_I2C_Driver_Out : public WipperSnapper_I2C_Driver { - -public: - /*! - @brief Creates a new I2C output component driver. - @param i2c - The I2C hardware interface, default is Wire. - @param sensorAddress - The I2C sensor's unique address. - */ - WipperSnapper_I2C_Driver_Out(TwoWire *i2c, uint16_t sensorAddress) - : WipperSnapper_I2C_Driver(i2c, sensorAddress) { - // No-op constructor - } - - /*! - @brief Destructor for an I2C output component. - */ - virtual ~WipperSnapper_I2C_Driver_Out() { - // No-op destructor - } - - /*! - @brief Writes a message to an i2c output device. - @param message - The message to be displayed. -*/ - virtual void WriteMessage(const char *message) { - // noop - } - - /*! - @brief Configures a SSD1306 OLED display. Must be called before driver - begin() - @param width - The width of the display in pixels. - @param height - The height of the display in pixels. - @param text_size - The display's text size. - @param rotation - The rotation of the display in degrees, default is 0. - */ - virtual void ConfigureSSD1306(uint8_t width, uint8_t height, - uint8_t text_size, uint8_t rotation = 0) { - // noop - } - - /*! - @brief Writes a message to the SSD1306 display. - @param message - The message to be displayed. - */ - virtual void WriteMessageSSD1306(const char *message) { - // noop - } - - /*! - @brief Configures a LED backpack. - @param brightness - The brightness of the LED backpack. - @param alignment - The alignment of the LED backpack. - */ - virtual void ConfigureI2CBackpack(int32_t brightness, uint32_t alignment) { - // noop - } - - /*! - @brief Sets the brightness of the LED backpack. - @param b - The brightness value, from 0 (off) to 15 (full brightness). - */ - virtual void SetLedBackpackBrightness(uint8_t b) { - // noop - } - - /*! - @brief Writes a message to the LED backpack. - @param msg_write - Pointer to a wippersnapper_i2c_v1_LedBackpackWrite message. - */ - void WriteLedBackpack(wippersnapper_i2c_v1_LEDBackpackWrite *msg_write) { - WriteMessage(msg_write->message); - } - - /*! - @brief Configures a character LCD. - @param rows - The number of rows in the LCD. - @param cols - The number of columns in the LCD. - */ - virtual void ConfigureCharLcd(uint32_t rows, uint32_t cols) { - // noop - } - - /*! - @brief Turns the character LCD backlight on or off. - @param enable - True to enable the backlight, false to disable it. - */ - void EnableCharLcdBacklight(bool enable) { - // noop - } - - /*! - @brief Writes a message to the LCD. - @param write_char_lcd - Points to a CharLCDWrite message. - @param enable_backlight - True if the backlight should be enabled, false otherwise. - */ - void WriteMessageCharLCD(wippersnapper_i2c_v1_CharLCDWrite *write_char_lcd, - bool enable_backlight = true) { - EnableCharLcdBacklight(enable_backlight); - WriteMessage(write_char_lcd->message); - } -}; - -#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_H diff --git a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_7Seg.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_7Seg.h deleted file mode 100644 index 1184e844a..000000000 --- a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_7Seg.h +++ /dev/null @@ -1,209 +0,0 @@ -/*! - * @file WipperSnapper_I2C_Driver_Out_7Seg.h - * - * Device driver designed specifically to work with the Adafruit LED 7-Segment - * I2C backpacks: - * ----> http://www.adafruit.com/products/881 - * ----> http://www.adafruit.com/products/880 - * ----> http://www.adafruit.com/products/879 - * ----> http://www.adafruit.com/products/878 - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell for Adafruit Industries 2025 - * - * MIT license, all text here must be included in any redistribution. - * - */ - -#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_7SEG_H -#define WIPPERSNAPPER_I2C_DRIVER_OUT_7SEG_H - -#include "WipperSnapper_I2C_Driver_Out.h" -#include -#include - -#define LED_BACKPACK_ALIGNMENT_UNSPECIFIED 0 ///< Unspecified alignment -#define LED_BACKPACK_ALIGNMENT_LEFT 1 ///< Left alignment -#define LED_BACKPACK_ALIGNMENT_RIGHT 2 ///< Right alignment -#define LED_BACKPACK_ALIGNMENT_DEFAULT \ - LED_BACKPACK_ALIGNMENT_LEFT ///< Default alignment -#define LED_MAX_CHARS \ - 5 ///< Maximum characters for 7-segment display, including ':' -#define LED_BACKPACK_DEGREE_SYMBOL \ - 0b01100011 ///< Degree symbol for 7-segment display - -/*! - @brief Class that provides a driver interface for 7-Segment - Displays w/I2C Backpack -*/ -class WipperSnapper_I2C_Driver_Out_7Seg : public WipperSnapper_I2C_Driver_Out { - -public: - /*******************************************************************************/ - /*! - @brief Constructor for a 7-Segment display driver. - @param i2c - The I2C interface. - @param sensorAddress - 7-bit device address. - */ - /*******************************************************************************/ - WipperSnapper_I2C_Driver_Out_7Seg(TwoWire *i2c, uint16_t sensorAddress) - : WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) { - _i2c = i2c; - _sensorAddress = sensorAddress; - } - - /*! - @brief Destructor for a 7-Segment display driver. - */ - ~WipperSnapper_I2C_Driver_Out_7Seg() { - if (_matrix != nullptr) { - delete _matrix; - _matrix = nullptr; - } - } - - /*! - @brief Initializes the 7-segment LED matrix and begins I2C - communication. - @returns True if initialized successfully, False otherwise. - */ - bool begin() { - _matrix = new Adafruit_7segment(); - bool did_begin = _matrix->begin(_sensorAddress, _i2c); - return did_begin; - } - - /*! - @brief Configures the LED matrix's I2C backpack. - @param brightness - The brightness of the i2c backpack (0-15). - @param alignment - The alignment of the i2c backpack's LED matrix (left/right). -*/ - void ConfigureI2CBackpack(int32_t brightness, uint32_t alignment) { - if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) { - _alignment = LED_BACKPACK_ALIGNMENT_RIGHT; - } else { - _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; - } - - // Note: Adafruit_LEDBackpack normalizes only > 15, but not < 0, - // so, here we're normalizing < 0 to 8 (median brightness) - if (brightness < 0) { - brightness = 8; // Set to median brightness if out of range - } - } - - /*! - @brief Sets the brightness of the LED backpack. - @param b - The brightness value, from 0 (off) to 15 (full brightness). - */ - void SetLedBackpackBrightness(uint8_t b) { - if (_matrix == nullptr) { - return; - } - _matrix->setBrightness(b); - } - - /*! - @brief Writes the first four characters of a message to the Adafruit - 7-segment LED matrix. - @param message - The message to be displayed. - */ - void WriteMessage(const char *message) { - if (_matrix == nullptr || message == nullptr) { - return; - } - - // Clear before writing - _matrix->clear(); - - // Calculate the number of characters to display - size_t len_display = min(strlen(message), (size_t)LED_MAX_CHARS); - - // Set the starting position based on alignment - int pos_start; - if (_alignment == LED_BACKPACK_ALIGNMENT_LEFT) { - pos_start = 0; // start at the leftmost position of the display - } else { - // Exclude decimal points from the character count because those get - // displayed on a "special" segment of the LED display - int seg_chars = 0; - for (size_t i = 0; i < len_display; i++) { - if (message[i] != '.') { - seg_chars++; - } - } - // start at the rightmost position of the display - switch (seg_chars) { - case 4: - pos_start = 0; - break; - case 3: - pos_start = 1; - break; - case 2: - pos_start = 3; // if 2 characters, start at position 3 is required - // because ':' is position 2 and we need to skip it - break; - case 1: - pos_start = 4; - break; - default: - pos_start = 0; // if no characters or overflow, start at position 0 - break; - } - } - - // Write to the display's buffer - int cur_idx = pos_start; - for (size_t i = 0; i < len_display; i++) { - - // skip position 2 - if (cur_idx == 2) { - cur_idx++; - } - // Save the character because if there's a decimal, we need to skip it in - // the buffer - char ch = message[i]; - - // Look-ahead for a decimal point to attach to the current character - bool display_dot = false; - if (i + 1 < len_display && message[i + 1] == '.') { - display_dot = true; - i++; - len_display++; - } else if (message[i] == 0xC2 && message[i + 1] == 0xB0 && - i + 1 < strlen(message)) { - // Write degree symbol - _matrix->writeDigitRaw(cur_idx, LED_BACKPACK_DEGREE_SYMBOL); - i++; - cur_idx++; - continue; // skip to next character - } - // Write the character to the display buffer - _matrix->writeDigitAscii(cur_idx, ch, display_dot); - cur_idx++; - } - // Issue the buffered data in RAM to the display - _matrix->writeDisplay(); - } - -protected: - Adafruit_7segment *_matrix = - nullptr; ///< ptr to a 7-segment LED matrix object - int32_t _brightness; ///< Brightness of the LED backpack, from 0 (off) to 15 - ///< (full brightness) - uint32_t _alignment = - LED_BACKPACK_ALIGNMENT_DEFAULT; ///< Determines L/R alignment of the - ///< message displayed -}; - -#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_7SEG_H \ No newline at end of file diff --git a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_CharLcd.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_CharLcd.h deleted file mode 100644 index e00572c81..000000000 --- a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_CharLcd.h +++ /dev/null @@ -1,163 +0,0 @@ -/*! - * @file WipperSnapper_I2C_Driver_Out_CharLcd.h - * - * Device driver for I2C Character LCDs (HD44780) - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell for Adafruit Industries 2025 - * - * MIT license, all text here must be included in any redistribution. - * - */ - -#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_CHARLCD_H -#define WIPPERSNAPPER_I2C_DRIVER_OUT_CHARLCD_H - -#include "WipperSnapper_I2C_Driver_Out.h" -#include - -/*! - @brief Class that provides a driver interface for a lcd character display. - This class is a wrapper around the Adafruit_LiquidCrystal library. -*/ -class WipperSnapper_I2C_Driver_Out_CharLcd - : public WipperSnapper_I2C_Driver_Out { - -public: - /*! - @brief Constructor for a LCD character display. - @param i2c - The I2C interface. - @param sensorAddress - 7-bit device address. - */ - WipperSnapper_I2C_Driver_Out_CharLcd(TwoWire *i2c, uint16_t sensorAddress) - : WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) { - _i2c = i2c; - _sensorAddress = sensorAddress; - } - - /*! - @brief Destructor for an MS8607 sensor. - */ - ~WipperSnapper_I2C_Driver_Out_CharLcd() { - if (_lcd != nullptr) { - delete _lcd; - _lcd = nullptr; - } - } - - /*! - @brief Initializes the drvOutQuadAlphaNum component and begins I2C. - @returns True if initialized successfully, False otherwise. - */ - bool begin() { - _lcd = new Adafruit_LiquidCrystal(_sensorAddress, _i2c); - bool did_begin = _lcd->begin(_cols, _rows); - if (did_begin) { - _lcd->setBacklight(HIGH); - } - return did_begin; - } - - /*! - @brief Writes a message to the LCD. - @note MUST be called prior to begin() to configure the LCD's size - @param rows - The number of rows in the LCD. - @param cols - The number of columns in the LCD. - */ - void ConfigureCharLcd(uint8_t rows, uint8_t cols) { - _rows = rows; - _cols = cols; - } - - /*! - @brief Turns the character LCD backlight on or off. - @param enable - True to enable the backlight, false to disable it. - */ - void EnableCharLcdBacklight(bool enable = true) { - if (_lcd == nullptr) - return; - - if (enable) { - _lcd->setBacklight(HIGH); - } else { - _lcd->setBacklight(LOW); - } - } - - /*! - @brief Writes a message to the LCD. - @param message - The message to be displayed. - */ - void WriteMessage(const char *message) { - if (_lcd == nullptr) - return; - - // Before writing, let's clear the display - _lcd->clear(); - - size_t message_length = strlen(message); - size_t cur_idx = 0; // Current index in the message - - // Write each row until it hits: \n, or the end of the message, or the last - // column/row position - for (int cur_row = 0; cur_row < _rows && cur_idx < message_length; - cur_row++) { - // Write each row out at the beginning of the row - _lcd->setCursor(0, cur_row); - for (int cur_col = 0; cur_col < _cols && cur_idx < message_length; - cur_col++) { - char c = message[cur_idx]; - if (c == '\\' && cur_idx + 1 < message_length && - (message[cur_idx + 1] == 'n' || message[cur_idx + 1] == 'r')) { - // Handle \r\n sequence as a single newline - if (message[cur_idx + 1] == 'r' && cur_idx + 3 < message_length && - message[cur_idx + 2] == '\\' && message[cur_idx + 3] == 'n') { - cur_idx += 4; // Skip \r\n and don't move the cursor two rows - break; // Move to the next row - } else { - if (message[cur_idx + 1] == 'r') { - _lcd->write('\\'); - _lcd->write('r'); - cur_idx += 2; // Skip the \r - } else { - cur_idx += 2; // Skip the \n - break; // Move to the next row - } - } - } else if ((c == 0x0A || c == 0x0D) && cur_idx + 1 < message_length) { - if (c == 0x0A && cur_idx + 1 < message_length && - message[cur_idx + 1] == 0x0D) { - cur_idx += 2; // Skip both LF and CR characters - } else { - cur_idx += 1; // Skip single newline character - } - break; // and move to the next row - } else if (c == 194 && cur_idx + 1 < message_length && - message[cur_idx + 1] == 176) { - cur_idx += 2; // Skip the degree symbol sequence in the buffer - _lcd->write(0xDF); // and write the degree symbol - } else { - _lcd->write(c); - cur_idx++; - } - } - } - } - -protected: - Adafruit_LiquidCrystal *_lcd = - nullptr; ///< Pointer to the Adafruit_LiquidCrystal object - uint8_t _rows; ///< Number of rows in the display - uint8_t _cols; ///< Number of columns in the display -}; - -#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_CHARLCD_H \ No newline at end of file diff --git a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h deleted file mode 100644 index 02553e208..000000000 --- a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h +++ /dev/null @@ -1,178 +0,0 @@ -/*! - * @file WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h - * - * Device driver for Quad Alphanumeric Displays w/I2C Backpack - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell for Adafruit Industries 2025 - * - * MIT license, all text here must be included in any redistribution. - * - */ - -#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_QUADALPHANUM_H -#define WIPPERSNAPPER_I2C_DRIVER_OUT_QUADALPHANUM_H - -#include "WipperSnapper_I2C_Driver_Out.h" -#include -#include - -#define LED_BACKPACK_ALIGNMENT_UNSPECIFIED 0 ///< Unspecified alignment -#define LED_BACKPACK_ALIGNMENT_LEFT 1 ///< Left alignment -#define LED_BACKPACK_ALIGNMENT_RIGHT 2 ///< Right alignment -#define LED_BACKPACK_ALIGNMENT_DEFAULT \ - LED_BACKPACK_ALIGNMENT_LEFT ///< Default alignment -#define LED_MAX_CHARS \ - 4 ///< Maximum number of characters to display on the alphanumeric display -#define ALPHANUM_DEGREE_SYMBOL \ - 0b0000000011100011 ///< Degree symbol for alphanumeric display - -/*! - @brief Class that provides a driver interface for Quad Alphanumeric - Displays w/I2C Backpack -*/ -class WipperSnapper_I2C_Driver_Out_QuadAlphaNum - : public WipperSnapper_I2C_Driver_Out { - -public: - /*******************************************************************************/ - /*! - @brief Constructor for an MS8607 sensor. - @param i2c - The I2C interface. - @param sensorAddress - 7-bit device address. - */ - /*******************************************************************************/ - WipperSnapper_I2C_Driver_Out_QuadAlphaNum(TwoWire *i2c, - uint16_t sensorAddress) - : WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) { - _i2c = i2c; - _sensorAddress = sensorAddress; - } - - /*! - @brief Destructor for an MS8607 sensor. - */ - ~WipperSnapper_I2C_Driver_Out_QuadAlphaNum() { - if (_alpha4 != nullptr) { - delete _alpha4; - _alpha4 = nullptr; - } - } - - /*! - @brief Initializes the drvOutQuadAlphaNum component and begins I2C. - @returns True if initialized successfully, False otherwise. - */ - bool begin() { - _alpha4 = new Adafruit_AlphaNum4(); - bool did_begin = _alpha4->begin(_sensorAddress, _i2c); - _alpha4->setBrightness(_brightness); - return did_begin; - } - - /*! - @brief Configures a LED backpack. - @param brightness - The brightness of the LED backpack. - @param alignment - The alignment of the LED backpack. -*/ - void ConfigureI2CBackpack(int32_t brightness, uint32_t alignment) { - if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) { - _alignment = LED_BACKPACK_ALIGNMENT_RIGHT; - } else { - _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; - } - _brightness = brightness; - } - - /*! - @brief Sets the brightness of the LED backpack. - @param b - The brightness value, from 0 (off) to 15 (full brightness). - */ - void SetLedBackpackBrightness(uint8_t b) { - if (_alpha4 == nullptr) { - return; - } - _alpha4->setBrightness(b); - } - - /*! - @brief Writes the first four characters of a message to the quad - alphanumeric display. - @param message - The message to be displayed. - */ - void WriteMessage(const char *message) { - if (_alpha4 == nullptr || message == nullptr) { - return; - } - // Clear before writing - _alpha4->clear(); - - // Calculate the number of characters to display - size_t len_display = min(strlen(message), (size_t)LED_MAX_CHARS); - - // Set the starting position based on alignment - int pos_start; - if (_alignment == LED_BACKPACK_ALIGNMENT_LEFT) { - pos_start = 0; // start at the leftmost position of the display - } else { - // Exclude decimal points from the character count because those get - // displayed on a "special" segment of the LED display - int seg_chars = 0; - for (size_t i = 0; i < len_display; i++) { - if (message[i] != '.') { - seg_chars++; - } - } - // start at the rightmost position of the display - pos_start = LED_MAX_CHARS - seg_chars; - } - - // Write to the display's buffer - int cur_idx = pos_start; - for (size_t i = 0; i < len_display; i++) { - // Save the character because if there's a decimal, we need to skip it in - // the buffer - char ch = message[i]; - - // Look-ahead for a decimal point to attach to the current character - bool display_dot = false; - if (i + 1 < len_display && message[i + 1] == '.') { - display_dot = true; - i++; - len_display++; - } else if (message[i] == 0xC2 && message[i + 1] == 0xB0 && - i + 1 < strlen(message)) { - // Write the degree symbol - _alpha4->writeDigitRaw(cur_idx, ALPHANUM_DEGREE_SYMBOL); - i++; - cur_idx++; - continue; - } - // Write the character to the display buffer - _alpha4->writeDigitAscii(cur_idx, ch, display_dot); - cur_idx++; - } - // Issue the buffered data in RAM to the display - _alpha4->writeDisplay(); - } - -protected: - Adafruit_AlphaNum4 *_alpha4 = - nullptr; ///< ptr to a 4-digit alphanumeric display object - int32_t _brightness; ///< Brightness of the LED backpack, from 0 (off) to 15 - ///< (full brightness) - uint32_t _alignment = - LED_BACKPACK_ALIGNMENT_DEFAULT; ///< Determines L/R alignment of the - ///< message displayed -}; - -#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_QUADALPHANUM_H \ No newline at end of file diff --git a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Sh1107.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Sh1107.h deleted file mode 100644 index 1ef27e450..000000000 --- a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Sh1107.h +++ /dev/null @@ -1,208 +0,0 @@ -/*! - * @file WipperSnapper_I2C_Driver_Out_SH1107.h - * - * Device driver for a SH1107 OLED Display - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Tyeth Gundry for Adafruit Industries 2025 - * - * MIT license, all text here must be included in any redistribution. - * - */ - -#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_SH1107_H -#define WIPPERSNAPPER_I2C_DRIVER_OUT_SH1107_H - -#include "WipperSnapper_I2C_Driver_Out.h" -#include -#include -#include - -#define WS_SH1107_DEFAULT_WIDTH \ - 128 ///< Default width for a sh1107 128x64 display -#define WS_SH1107_DEFAULT_HEIGHT \ - 64 ///< Default height for a sh1107 128x64 display - -#define OLED_128X64_WING_WIDTH 128 ///< Width of the 128x64 OLED FeatherWing -#define OLED_128X64_WING_HEIGHT 64 ///< Height of the 128x64 OLED FeatherWing -#define OLED_128X64_WING_ROTATION_90 1 ///< Rotation of OLED FeatherWing 0-3 - -/*! - @brief Class that provides a driver interface for a SH1107 - OLED Display -*/ -class WipperSnapper_I2C_Driver_Out_SH1107 - : public WipperSnapper_I2C_Driver_Out { - -public: - /*******************************************************************************/ - /*! - @brief Constructor for an SH1107 OLED display. - @param i2c - The I2C interface. - @param sensorAddress - 7-bit device address. - */ - /*******************************************************************************/ - WipperSnapper_I2C_Driver_Out_SH1107(TwoWire *i2c, uint16_t sensorAddress) - : WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) { - _i2c = i2c; - _sensorAddress = sensorAddress; - _width = WS_SH1107_DEFAULT_WIDTH; - _height = WS_SH1107_DEFAULT_HEIGHT; - } - - /*! - @brief Destructor for a SH1107 OLED display. - */ - ~WipperSnapper_I2C_Driver_Out_SH1107() { - if (_display != nullptr) { - _display->clearDisplay(); - _display->display(); - _display->oled_command(SH110X_DISPLAYOFF); - delete _display; - _display = nullptr; - } - } - - /*! - @brief Initializes the SH1107 display and begins I2C. - @returns True if initialized successfully, False otherwise. - */ - bool begin() { - if (_width == OLED_128X64_WING_WIDTH && - _height == OLED_128X64_WING_HEIGHT && - _rotation == OLED_128X64_WING_ROTATION_90) { - // featherwing needs to be rotated 90 degrees and swap w/h ctor args - _display = new Adafruit_SH1107(_height, _width, _i2c); - } else { - _display = new Adafruit_SH1107(_width, _height, _i2c); - } - if (!_display->begin(_sensorAddress, true)) - return false; - - // Clear the buffer. - _display->clearDisplay(); - _display->display(); - _display->setRotation(_rotation); // 0-3, not degrees for SH1107 - - // Configure the text size and color - _display->setTextSize(_text_sz); - _display->setTextColor(SH110X_WHITE); - _display->setCursor(0, 0); - // Clear the buffer - _display->clearDisplay(); - _display->display(); - return true; - } - - /*! - @brief Configures a SH1107 OLED display. Must be called before driver - begin() - @param width - The width of the display in pixels. - @param height - The height of the display in pixels. - @param text_size - The magnification factor for the text size. - @param rotation - The rotation of the display in degrees, default is 0. - */ - void ConfigureSH1107(uint8_t width, uint8_t height, uint8_t text_size, - uint8_t rotation) { - _width = width; - _height = height; - _text_sz = text_size; - _rotation = - rotation % 90; // SH1107 requires rotation to be 0-3, not degrees - } - /*! - @brief Configures a SSD1306 OLED display. Must be called before driver - begin() - This is a fake function to match the SSD1306 interface. - @param width - The width of the display in pixels. - @param height - The height of the display in pixels. - @param text_size - The magnification factor for the text size. - @param rotation - The rotation of the display in degrees, default is 0. - */ - void ConfigureSSD1306(uint8_t width, uint8_t height, uint8_t text_size, - uint8_t rotation) { - // This is a SH1107, not a SSD1306, so we don't need to do anything here. - ConfigureSH1107(width, height, text_size, rotation); - } - - /*! - @brief Writes a message to the SH1107 display. - @param message - The message to be displayed. - */ - void WriteMessageSH1107(const char *message) { - if (_display == nullptr) - return; - // Start with a fresh display buffer - // and settings - int16_t y_idx = 0; - _display->clearDisplay(); - _display->setTextSize(_text_sz); - _display->setTextColor(SH110X_WHITE); - _display->setCursor(0, y_idx); - _display->display(); - - // Calculate the line height based on the text size (NOTE: base height is - // 8px) - int16_t line_height = 8 * _text_sz; - uint16_t c_idx = 0; - size_t msg_size = strlen(message); - for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) { - if (message[i] == '\\' && i + 1 < msg_size && - (message[i + 1] == 'n' || message[i + 1] == 'r')) { - // Handle \r\n sequence as a single newline - if (message[i + 1] == 'r' && i + 3 < msg_size && - message[i + 2] == '\\' && message[i + 3] == 'n') { - // Skip to the next line - y_idx += line_height; - _display->setCursor(0, y_idx); - i += 3; - } else if (message[i + 1] == 'n') { - // Skip to the next line - y_idx += line_height; - _display->setCursor(0, y_idx); - i++; - } - } else if (message[i] == 0xC2 && message[i + 1] == 0xB0) { - _display->write(char(248)); - _display->display(); - i++; - } else { - _display->print(message[i]); - _display->display(); - } - } - } - - /*! - @brief Writes a message to the fake "SSD1306" SH1107 display. - @param message - The message to be displayed. - */ - void WriteMessageSSD1306(const char *message) { - // This is a SH1107, not a SSD1306, so we just call the SH1107 write - WriteMessageSH1107(message); - } - -protected: - Adafruit_SH1107 *_display = - nullptr; ///< Pointer to the Adafruit_SH1107 object - uint8_t _width; ///< Width of the display in pixels - uint8_t _height; ///< Height of the display in pixels - uint8_t _rotation; ///< Rotation of the display (0-3) - uint8_t _text_sz; ///< Text size of the display -}; - -#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_SH1107_H diff --git a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Ssd1306.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Ssd1306.h deleted file mode 100644 index 454a5852f..000000000 --- a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Ssd1306.h +++ /dev/null @@ -1,166 +0,0 @@ -/*! - * @file WipperSnapper_I2C_Driver_Out_Ssd1306.h - * - * Device driver for a SSD1306 OLED Display - * - * Adafruit invests time and resources providing this open source code, - * please support Adafruit and open-source hardware by purchasing - * products from Adafruit! - * - * Copyright (c) Brent Rubell for Adafruit Industries 2025 - * - * MIT license, all text here must be included in any redistribution. - * - */ - -#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_SSD1306_H -#define WIPPERSNAPPER_I2C_DRIVER_OUT_SSD1306_H - -#include "WipperSnapper_I2C_Driver_Out.h" -#include -#include - -#define WS_SSD1306_DEFAULT_WIDTH \ - 128 ///< Default width for a ssd1306 128x64 display -#define WS_SSD1306_DEFAULT_HEIGHT \ - 64 ///< Default height for a ssd1306 128x64 display - -/*! - @brief Class that provides a driver interface for a SSD1306 - OLED Display -*/ -class WipperSnapper_I2C_Driver_Out_Ssd1306 - : public WipperSnapper_I2C_Driver_Out { - -public: - /*******************************************************************************/ - /*! - @brief Constructor for a SSD1306 OLED display. - @param i2c - The I2C interface. - @param sensorAddress - 7-bit device address. - */ - /*******************************************************************************/ - WipperSnapper_I2C_Driver_Out_Ssd1306(TwoWire *i2c, uint16_t sensorAddress) - : WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) { - _i2c = i2c; - _sensorAddress = sensorAddress; - _width = WS_SSD1306_DEFAULT_WIDTH; - _height = WS_SSD1306_DEFAULT_HEIGHT; - } - - /*! - @brief Destructor for a SSD1306 OLED display. - */ - ~WipperSnapper_I2C_Driver_Out_Ssd1306() { - if (_display != nullptr) { - _display->clearDisplay(); - _display->display(); - _display->ssd1306_command(SSD1306_DISPLAYOFF); - delete _display; - _display = nullptr; - } - } - - /*! - @brief Initializes the SSD1306 display and begins I2C. - @returns True if initialized successfully, False otherwise. - */ - bool begin() { - // Attempt to create and allocate a SSD1306 obj. - _display = new Adafruit_SSD1306(_width, _height, _i2c); - if (!_display->begin(SSD1306_SWITCHCAPVCC, _sensorAddress)) - return false; - // Configure the rotation, text size and color - _display->setRotation(_rotation); - _display->setTextSize(_text_sz); - _display->setTextColor(SSD1306_WHITE); - // Use full 256 char 'Code Page 437' font - _display->cp437(true); - // Clear the buffer - _display->clearDisplay(); - _display->display(); - return true; - } - - /*! - @brief Configures a SSD1306 OLED display. Must be called before driver - begin() - @param width - The width of the display in pixels. - @param height - The height of the display in pixels. - @param text_size - The magnification factor for the text size. - @param rotation - The rotation of the display in degrees, default is 0. - */ - void ConfigureSSD1306(uint8_t width, uint8_t height, uint8_t text_size, - uint8_t rotation = 0) { - _width = width; - _height = height; - _text_sz = text_size; - _rotation = rotation; - } - - /*! - @brief Writes a message to the SSD1306 display. - @param message - The message to be displayed. - */ - void WriteMessageSSD1306(const char *message) { - if (_display == nullptr) - return; - - // Start with a fresh display buffer - // and settings - int16_t y_idx = 0; - _display->clearDisplay(); - _display->setTextSize(_text_sz); - _display->setTextColor(SSD1306_WHITE); - _display->setCursor(0, y_idx); - _display->display(); - - // Calculate the line height based on the text size (NOTE: base height is - // 8px) - int16_t line_height = 8 * _text_sz; - uint16_t c_idx = 0; - size_t msg_size = strlen(message); - for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) { - if (message[i] == '\\' && i + 1 < msg_size && - (message[i + 1] == 'n' || message[i + 1] == 'r')) { - // Handle \r\n sequence as a single newline - if (message[i + 1] == 'r' && i + 3 < msg_size && - message[i + 2] == '\\' && message[i + 3] == 'n') { - // Skip to the next line - y_idx += line_height; - _display->setCursor(0, y_idx); - i += 3; - } else if (message[i + 1] == 'n') { - // Skip to the next line - y_idx += line_height; - _display->setCursor(0, y_idx); - i++; - } - } else if (message[i] == 0xC2 && message[i + 1] == 0xB0) { - _display->write(char(248)); - _display->display(); - i++; - } else { - _display->print(message[i]); - _display->display(); - } - } - } - -protected: - Adafruit_SSD1306 *_display = - nullptr; ///< Pointer to the Adafruit_SSD1306 object - uint8_t _width; ///< Width of the display in pixels - uint8_t _height; ///< Height of the display in pixels - uint8_t _rotation; ///< Rotation of the display in degrees - uint8_t _text_sz; ///< Text size of the display -}; - -#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_SSD1306_H \ No newline at end of file diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index 8d8cb3aea..5e84e10ff 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index d09c6efb8..e1ceb5aad 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 39fe9aca8..08385fe52 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,12 +1,12 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif -PB_BIND(wippersnapper_display_v1_EpdSpiConfig, wippersnapper_display_v1_EpdSpiConfig, AUTO) +PB_BIND(wippersnapper_display_v1_SpiConfig, wippersnapper_display_v1_SpiConfig, AUTO) PB_BIND(wippersnapper_display_v1_EPDConfig, wippersnapper_display_v1_EPDConfig, AUTO) @@ -15,13 +15,22 @@ PB_BIND(wippersnapper_display_v1_EPDConfig, wippersnapper_display_v1_EPDConfig, PB_BIND(wippersnapper_display_v1_EPDWriteOptions, wippersnapper_display_v1_EPDWriteOptions, AUTO) -PB_BIND(wippersnapper_display_v1_TftSpiConfig, wippersnapper_display_v1_TftSpiConfig, AUTO) +PB_BIND(wippersnapper_display_v1_TftConfig, wippersnapper_display_v1_TftConfig, AUTO) -PB_BIND(wippersnapper_display_v1_TftConfig, wippersnapper_display_v1_TftConfig, AUTO) +PB_BIND(wippersnapper_display_v1_I2cConfig, wippersnapper_display_v1_I2cConfig, 2) + + +PB_BIND(wippersnapper_display_v1_SSD1306Config, wippersnapper_display_v1_SSD1306Config, AUTO) + +PB_BIND(wippersnapper_display_v1_LEDBackpackConfig, wippersnapper_display_v1_LEDBackpackConfig, AUTO) -PB_BIND(wippersnapper_display_v1_DisplayAddOrReplace, wippersnapper_display_v1_DisplayAddOrReplace, AUTO) + +PB_BIND(wippersnapper_display_v1_CharLCDConfig, wippersnapper_display_v1_CharLCDConfig, AUTO) + + +PB_BIND(wippersnapper_display_v1_DisplayAddOrReplace, wippersnapper_display_v1_DisplayAddOrReplace, 2) PB_BIND(wippersnapper_display_v1_DisplayRemove, wippersnapper_display_v1_DisplayRemove, AUTO) @@ -39,3 +48,5 @@ PB_BIND(wippersnapper_display_v1_DisplayRemoved, wippersnapper_display_v1_Displa + + diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index 1c31c7661..ba8c3675f 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -25,7 +25,24 @@ typedef enum _wippersnapper_display_v1_EPDMode { wippersnapper_display_v1_EPDMode_EPD_MODE_MONO = 2 } wippersnapper_display_v1_EPDMode; +typedef enum _wippersnapper_display_v1_SSD1306TextSize { + wippersnapper_display_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_UNSPECIFIED = 0, + wippersnapper_display_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_1 = 1, + wippersnapper_display_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_2 = 2 +} wippersnapper_display_v1_SSD1306TextSize; + +typedef enum _wippersnapper_display_v1_LEDBackpackAlignment { + wippersnapper_display_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_UNSPECIFIED = 0, + wippersnapper_display_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_LEFT = 1, + wippersnapper_display_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT = 2 +} wippersnapper_display_v1_LEDBackpackAlignment; + /* Struct definitions */ +typedef struct _wippersnapper_display_v1_CharLCDConfig { + uint32_t rows; + uint32_t columns; +} wippersnapper_display_v1_CharLCDConfig; + typedef struct _wippersnapper_display_v1_DisplayAddedorReplaced { char name[64]; bool did_add; @@ -48,14 +65,33 @@ typedef struct _wippersnapper_display_v1_EPDWriteOptions { int32_t text_size; } wippersnapper_display_v1_EPDWriteOptions; -typedef struct _wippersnapper_display_v1_EpdSpiConfig { +typedef struct _wippersnapper_display_v1_I2cConfig { + bool has_i2c; + wippersnapper_i2c_v1_I2CDeviceInitRequest i2c; +} wippersnapper_display_v1_I2cConfig; + +typedef struct _wippersnapper_display_v1_LEDBackpackConfig { + int32_t brightness; + wippersnapper_display_v1_LEDBackpackAlignment alignment; +} wippersnapper_display_v1_LEDBackpackConfig; + +typedef struct _wippersnapper_display_v1_SSD1306Config { + uint32_t width; + uint32_t height; + wippersnapper_display_v1_SSD1306TextSize text_size; +} wippersnapper_display_v1_SSD1306Config; + +typedef struct _wippersnapper_display_v1_SpiConfig { int32_t bus; char pin_dc[6]; char pin_rst[6]; char pin_cs[6]; char pin_sram_cs[6]; char pin_busy[6]; -} wippersnapper_display_v1_EpdSpiConfig; + char pin_mosi[6]; + char pin_sck[6]; + char pin_miso[6]; +} wippersnapper_display_v1_SpiConfig; typedef struct _wippersnapper_display_v1_TftConfig { int32_t width; @@ -63,28 +99,21 @@ typedef struct _wippersnapper_display_v1_TftConfig { int32_t rotation; } wippersnapper_display_v1_TftConfig; -typedef struct _wippersnapper_display_v1_TftSpiConfig { - int32_t bus; - char pin_cs[6]; - char pin_dc[6]; - char pin_mosi[6]; - char pin_sck[6]; - char pin_rst[6]; - char pin_miso[6]; -} wippersnapper_display_v1_TftSpiConfig; - typedef struct _wippersnapper_display_v1_DisplayAddOrReplace { wippersnapper_display_v1_DisplayType type; char name[64]; pb_size_t which_interface_type; union { - wippersnapper_display_v1_EpdSpiConfig spi_epd; - wippersnapper_display_v1_TftSpiConfig spi_tft; + wippersnapper_display_v1_SpiConfig cfg_spi; + wippersnapper_display_v1_I2cConfig cfg_i2c; } interface_type; pb_size_t which_config; union { wippersnapper_display_v1_EPDConfig config_epd; wippersnapper_display_v1_TftConfig config_tft; + wippersnapper_display_v1_SSD1306Config config_ssd1306; + wippersnapper_display_v1_LEDBackpackConfig config_led_backpack; + wippersnapper_display_v1_CharLCDConfig config_char_lcd; } config; } wippersnapper_display_v1_DisplayAddOrReplace; @@ -107,34 +136,50 @@ typedef struct _wippersnapper_display_v1_DisplayWrite { #define _wippersnapper_display_v1_EPDMode_MAX wippersnapper_display_v1_EPDMode_EPD_MODE_MONO #define _wippersnapper_display_v1_EPDMode_ARRAYSIZE ((wippersnapper_display_v1_EPDMode)(wippersnapper_display_v1_EPDMode_EPD_MODE_MONO+1)) +#define _wippersnapper_display_v1_SSD1306TextSize_MIN wippersnapper_display_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_UNSPECIFIED +#define _wippersnapper_display_v1_SSD1306TextSize_MAX wippersnapper_display_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_2 +#define _wippersnapper_display_v1_SSD1306TextSize_ARRAYSIZE ((wippersnapper_display_v1_SSD1306TextSize)(wippersnapper_display_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_2+1)) + +#define _wippersnapper_display_v1_LEDBackpackAlignment_MIN wippersnapper_display_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_UNSPECIFIED +#define _wippersnapper_display_v1_LEDBackpackAlignment_MAX wippersnapper_display_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT +#define _wippersnapper_display_v1_LEDBackpackAlignment_ARRAYSIZE ((wippersnapper_display_v1_LEDBackpackAlignment)(wippersnapper_display_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT+1)) + #ifdef __cplusplus extern "C" { #endif /* Initializer values for message structs */ -#define wippersnapper_display_v1_EpdSpiConfig_init_default {0, "", "", "", "", ""} +#define wippersnapper_display_v1_SpiConfig_init_default {0, "", "", "", "", "", "", "", ""} #define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN} #define wippersnapper_display_v1_EPDWriteOptions_init_default {0} -#define wippersnapper_display_v1_TftSpiConfig_init_default {0, "", "", "", "", "", ""} #define wippersnapper_display_v1_TftConfig_init_default {0, 0, 0} -#define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} +#define wippersnapper_display_v1_I2cConfig_init_default {false, wippersnapper_i2c_v1_I2CDeviceInitRequest_init_default} +#define wippersnapper_display_v1_SSD1306Config_init_default {0, 0, _wippersnapper_display_v1_SSD1306TextSize_MIN} +#define wippersnapper_display_v1_LEDBackpackConfig_init_default {0, _wippersnapper_display_v1_LEDBackpackAlignment_MIN} +#define wippersnapper_display_v1_CharLCDConfig_init_default {0, 0} +#define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_SpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} #define wippersnapper_display_v1_DisplayRemove_init_default {""} #define wippersnapper_display_v1_DisplayWrite_init_default {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_default}} #define wippersnapper_display_v1_DisplayAddedorReplaced_init_default {"", 0} #define wippersnapper_display_v1_DisplayRemoved_init_default {"", 0} -#define wippersnapper_display_v1_EpdSpiConfig_init_zero {0, "", "", "", "", ""} +#define wippersnapper_display_v1_SpiConfig_init_zero {0, "", "", "", "", "", "", "", ""} #define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN} #define wippersnapper_display_v1_EPDWriteOptions_init_zero {0} -#define wippersnapper_display_v1_TftSpiConfig_init_zero {0, "", "", "", "", "", ""} #define wippersnapper_display_v1_TftConfig_init_zero {0, 0, 0} -#define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} +#define wippersnapper_display_v1_I2cConfig_init_zero {false, wippersnapper_i2c_v1_I2CDeviceInitRequest_init_zero} +#define wippersnapper_display_v1_SSD1306Config_init_zero {0, 0, _wippersnapper_display_v1_SSD1306TextSize_MIN} +#define wippersnapper_display_v1_LEDBackpackConfig_init_zero {0, _wippersnapper_display_v1_LEDBackpackAlignment_MIN} +#define wippersnapper_display_v1_CharLCDConfig_init_zero {0, 0} +#define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_SpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} #define wippersnapper_display_v1_DisplayRemove_init_zero {""} #define wippersnapper_display_v1_DisplayWrite_init_zero {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_zero}} #define wippersnapper_display_v1_DisplayAddedorReplaced_init_zero {"", 0} #define wippersnapper_display_v1_DisplayRemoved_init_zero {"", 0} /* Field tags (for use in manual encoding/decoding) */ +#define wippersnapper_display_v1_CharLCDConfig_rows_tag 1 +#define wippersnapper_display_v1_CharLCDConfig_columns_tag 2 #define wippersnapper_display_v1_DisplayAddedorReplaced_name_tag 1 #define wippersnapper_display_v1_DisplayAddedorReplaced_did_add_tag 2 #define wippersnapper_display_v1_DisplayRemove_name_tag 1 @@ -142,42 +187,50 @@ extern "C" { #define wippersnapper_display_v1_DisplayRemoved_did_remove_tag 2 #define wippersnapper_display_v1_EPDConfig_mode_tag 1 #define wippersnapper_display_v1_EPDWriteOptions_text_size_tag 1 -#define wippersnapper_display_v1_EpdSpiConfig_bus_tag 1 -#define wippersnapper_display_v1_EpdSpiConfig_pin_dc_tag 2 -#define wippersnapper_display_v1_EpdSpiConfig_pin_rst_tag 3 -#define wippersnapper_display_v1_EpdSpiConfig_pin_cs_tag 4 -#define wippersnapper_display_v1_EpdSpiConfig_pin_sram_cs_tag 5 -#define wippersnapper_display_v1_EpdSpiConfig_pin_busy_tag 6 +#define wippersnapper_display_v1_I2cConfig_i2c_tag 1 +#define wippersnapper_display_v1_LEDBackpackConfig_brightness_tag 1 +#define wippersnapper_display_v1_LEDBackpackConfig_alignment_tag 2 +#define wippersnapper_display_v1_SSD1306Config_width_tag 1 +#define wippersnapper_display_v1_SSD1306Config_height_tag 2 +#define wippersnapper_display_v1_SSD1306Config_text_size_tag 3 +#define wippersnapper_display_v1_SpiConfig_bus_tag 1 +#define wippersnapper_display_v1_SpiConfig_pin_dc_tag 2 +#define wippersnapper_display_v1_SpiConfig_pin_rst_tag 3 +#define wippersnapper_display_v1_SpiConfig_pin_cs_tag 4 +#define wippersnapper_display_v1_SpiConfig_pin_sram_cs_tag 5 +#define wippersnapper_display_v1_SpiConfig_pin_busy_tag 6 +#define wippersnapper_display_v1_SpiConfig_pin_mosi_tag 7 +#define wippersnapper_display_v1_SpiConfig_pin_sck_tag 8 +#define wippersnapper_display_v1_SpiConfig_pin_miso_tag 9 #define wippersnapper_display_v1_TftConfig_width_tag 1 #define wippersnapper_display_v1_TftConfig_height_tag 2 #define wippersnapper_display_v1_TftConfig_rotation_tag 3 -#define wippersnapper_display_v1_TftSpiConfig_bus_tag 1 -#define wippersnapper_display_v1_TftSpiConfig_pin_cs_tag 2 -#define wippersnapper_display_v1_TftSpiConfig_pin_dc_tag 3 -#define wippersnapper_display_v1_TftSpiConfig_pin_mosi_tag 4 -#define wippersnapper_display_v1_TftSpiConfig_pin_sck_tag 5 -#define wippersnapper_display_v1_TftSpiConfig_pin_rst_tag 6 -#define wippersnapper_display_v1_TftSpiConfig_pin_miso_tag 7 #define wippersnapper_display_v1_DisplayAddOrReplace_type_tag 1 #define wippersnapper_display_v1_DisplayAddOrReplace_name_tag 2 -#define wippersnapper_display_v1_DisplayAddOrReplace_spi_epd_tag 3 -#define wippersnapper_display_v1_DisplayAddOrReplace_spi_tft_tag 4 +#define wippersnapper_display_v1_DisplayAddOrReplace_cfg_spi_tag 3 +#define wippersnapper_display_v1_DisplayAddOrReplace_cfg_i2c_tag 4 #define wippersnapper_display_v1_DisplayAddOrReplace_config_epd_tag 5 #define wippersnapper_display_v1_DisplayAddOrReplace_config_tft_tag 6 +#define wippersnapper_display_v1_DisplayAddOrReplace_config_ssd1306_tag 7 +#define wippersnapper_display_v1_DisplayAddOrReplace_config_led_backpack_tag 8 +#define wippersnapper_display_v1_DisplayAddOrReplace_config_char_lcd_tag 9 #define wippersnapper_display_v1_DisplayWrite_name_tag 1 #define wippersnapper_display_v1_DisplayWrite_message_tag 2 #define wippersnapper_display_v1_DisplayWrite_epd_options_tag 3 /* Struct field encoding specification for nanopb */ -#define wippersnapper_display_v1_EpdSpiConfig_FIELDLIST(X, a) \ +#define wippersnapper_display_v1_SpiConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, bus, 1) \ X(a, STATIC, SINGULAR, STRING, pin_dc, 2) \ X(a, STATIC, SINGULAR, STRING, pin_rst, 3) \ X(a, STATIC, SINGULAR, STRING, pin_cs, 4) \ X(a, STATIC, SINGULAR, STRING, pin_sram_cs, 5) \ -X(a, STATIC, SINGULAR, STRING, pin_busy, 6) -#define wippersnapper_display_v1_EpdSpiConfig_CALLBACK NULL -#define wippersnapper_display_v1_EpdSpiConfig_DEFAULT NULL +X(a, STATIC, SINGULAR, STRING, pin_busy, 6) \ +X(a, STATIC, SINGULAR, STRING, pin_mosi, 7) \ +X(a, STATIC, SINGULAR, STRING, pin_sck, 8) \ +X(a, STATIC, SINGULAR, STRING, pin_miso, 9) +#define wippersnapper_display_v1_SpiConfig_CALLBACK NULL +#define wippersnapper_display_v1_SpiConfig_DEFAULT NULL #define wippersnapper_display_v1_EPDConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, mode, 1) @@ -189,17 +242,6 @@ X(a, STATIC, SINGULAR, INT32, text_size, 1) #define wippersnapper_display_v1_EPDWriteOptions_CALLBACK NULL #define wippersnapper_display_v1_EPDWriteOptions_DEFAULT NULL -#define wippersnapper_display_v1_TftSpiConfig_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, INT32, bus, 1) \ -X(a, STATIC, SINGULAR, STRING, pin_cs, 2) \ -X(a, STATIC, SINGULAR, STRING, pin_dc, 3) \ -X(a, STATIC, SINGULAR, STRING, pin_mosi, 4) \ -X(a, STATIC, SINGULAR, STRING, pin_sck, 5) \ -X(a, STATIC, SINGULAR, STRING, pin_rst, 6) \ -X(a, STATIC, SINGULAR, STRING, pin_miso, 7) -#define wippersnapper_display_v1_TftSpiConfig_CALLBACK NULL -#define wippersnapper_display_v1_TftSpiConfig_DEFAULT NULL - #define wippersnapper_display_v1_TftConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, width, 1) \ X(a, STATIC, SINGULAR, INT32, height, 2) \ @@ -207,19 +249,50 @@ X(a, STATIC, SINGULAR, INT32, rotation, 3) #define wippersnapper_display_v1_TftConfig_CALLBACK NULL #define wippersnapper_display_v1_TftConfig_DEFAULT NULL +#define wippersnapper_display_v1_I2cConfig_FIELDLIST(X, a) \ +X(a, STATIC, OPTIONAL, MESSAGE, i2c, 1) +#define wippersnapper_display_v1_I2cConfig_CALLBACK NULL +#define wippersnapper_display_v1_I2cConfig_DEFAULT NULL +#define wippersnapper_display_v1_I2cConfig_i2c_MSGTYPE wippersnapper_i2c_v1_I2CDeviceInitRequest + +#define wippersnapper_display_v1_SSD1306Config_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, width, 1) \ +X(a, STATIC, SINGULAR, UINT32, height, 2) \ +X(a, STATIC, SINGULAR, UENUM, text_size, 3) +#define wippersnapper_display_v1_SSD1306Config_CALLBACK NULL +#define wippersnapper_display_v1_SSD1306Config_DEFAULT NULL + +#define wippersnapper_display_v1_LEDBackpackConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, brightness, 1) \ +X(a, STATIC, SINGULAR, UENUM, alignment, 2) +#define wippersnapper_display_v1_LEDBackpackConfig_CALLBACK NULL +#define wippersnapper_display_v1_LEDBackpackConfig_DEFAULT NULL + +#define wippersnapper_display_v1_CharLCDConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, rows, 1) \ +X(a, STATIC, SINGULAR, UINT32, columns, 2) +#define wippersnapper_display_v1_CharLCDConfig_CALLBACK NULL +#define wippersnapper_display_v1_CharLCDConfig_DEFAULT NULL + #define wippersnapper_display_v1_DisplayAddOrReplace_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, type, 1) \ X(a, STATIC, SINGULAR, STRING, name, 2) \ -X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_epd,interface_type.spi_epd), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_tft,interface_type.spi_tft), 4) \ +X(a, STATIC, ONEOF, MESSAGE, (interface_type,cfg_spi,interface_type.cfg_spi), 3) \ +X(a, STATIC, ONEOF, MESSAGE, (interface_type,cfg_i2c,interface_type.cfg_i2c), 4) \ X(a, STATIC, ONEOF, MESSAGE, (config,config_epd,config.config_epd), 5) \ -X(a, STATIC, ONEOF, MESSAGE, (config,config_tft,config.config_tft), 6) +X(a, STATIC, ONEOF, MESSAGE, (config,config_tft,config.config_tft), 6) \ +X(a, STATIC, ONEOF, MESSAGE, (config,config_ssd1306,config.config_ssd1306), 7) \ +X(a, STATIC, ONEOF, MESSAGE, (config,config_led_backpack,config.config_led_backpack), 8) \ +X(a, STATIC, ONEOF, MESSAGE, (config,config_char_lcd,config.config_char_lcd), 9) #define wippersnapper_display_v1_DisplayAddOrReplace_CALLBACK NULL #define wippersnapper_display_v1_DisplayAddOrReplace_DEFAULT NULL -#define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_spi_epd_MSGTYPE wippersnapper_display_v1_EpdSpiConfig -#define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_spi_tft_MSGTYPE wippersnapper_display_v1_TftSpiConfig +#define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_cfg_spi_MSGTYPE wippersnapper_display_v1_SpiConfig +#define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_cfg_i2c_MSGTYPE wippersnapper_display_v1_I2cConfig #define wippersnapper_display_v1_DisplayAddOrReplace_config_config_epd_MSGTYPE wippersnapper_display_v1_EPDConfig #define wippersnapper_display_v1_DisplayAddOrReplace_config_config_tft_MSGTYPE wippersnapper_display_v1_TftConfig +#define wippersnapper_display_v1_DisplayAddOrReplace_config_config_ssd1306_MSGTYPE wippersnapper_display_v1_SSD1306Config +#define wippersnapper_display_v1_DisplayAddOrReplace_config_config_led_backpack_MSGTYPE wippersnapper_display_v1_LEDBackpackConfig +#define wippersnapper_display_v1_DisplayAddOrReplace_config_config_char_lcd_MSGTYPE wippersnapper_display_v1_CharLCDConfig #define wippersnapper_display_v1_DisplayRemove_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, name, 1) @@ -246,11 +319,14 @@ X(a, STATIC, SINGULAR, BOOL, did_remove, 2) #define wippersnapper_display_v1_DisplayRemoved_CALLBACK NULL #define wippersnapper_display_v1_DisplayRemoved_DEFAULT NULL -extern const pb_msgdesc_t wippersnapper_display_v1_EpdSpiConfig_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_SpiConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_EPDConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_EPDWriteOptions_msg; -extern const pb_msgdesc_t wippersnapper_display_v1_TftSpiConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_TftConfig_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_I2cConfig_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_SSD1306Config_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_LEDBackpackConfig_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_CharLCDConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayAddOrReplace_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemove_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayWrite_msg; @@ -258,11 +334,14 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayAddedorReplaced_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define wippersnapper_display_v1_EpdSpiConfig_fields &wippersnapper_display_v1_EpdSpiConfig_msg +#define wippersnapper_display_v1_SpiConfig_fields &wippersnapper_display_v1_SpiConfig_msg #define wippersnapper_display_v1_EPDConfig_fields &wippersnapper_display_v1_EPDConfig_msg #define wippersnapper_display_v1_EPDWriteOptions_fields &wippersnapper_display_v1_EPDWriteOptions_msg -#define wippersnapper_display_v1_TftSpiConfig_fields &wippersnapper_display_v1_TftSpiConfig_msg #define wippersnapper_display_v1_TftConfig_fields &wippersnapper_display_v1_TftConfig_msg +#define wippersnapper_display_v1_I2cConfig_fields &wippersnapper_display_v1_I2cConfig_msg +#define wippersnapper_display_v1_SSD1306Config_fields &wippersnapper_display_v1_SSD1306Config_msg +#define wippersnapper_display_v1_LEDBackpackConfig_fields &wippersnapper_display_v1_LEDBackpackConfig_msg +#define wippersnapper_display_v1_CharLCDConfig_fields &wippersnapper_display_v1_CharLCDConfig_msg #define wippersnapper_display_v1_DisplayAddOrReplace_fields &wippersnapper_display_v1_DisplayAddOrReplace_msg #define wippersnapper_display_v1_DisplayRemove_fields &wippersnapper_display_v1_DisplayRemove_msg #define wippersnapper_display_v1_DisplayWrite_fields &wippersnapper_display_v1_DisplayWrite_msg @@ -270,12 +349,15 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; #define wippersnapper_display_v1_DisplayRemoved_fields &wippersnapper_display_v1_DisplayRemoved_msg /* Maximum encoded size of messages (where known) */ -#define wippersnapper_display_v1_EpdSpiConfig_size 46 +#define wippersnapper_display_v1_SpiConfig_size 67 #define wippersnapper_display_v1_EPDConfig_size 2 #define wippersnapper_display_v1_EPDWriteOptions_size 11 -#define wippersnapper_display_v1_TftSpiConfig_size 53 #define wippersnapper_display_v1_TftConfig_size 33 -#define wippersnapper_display_v1_DisplayAddOrReplace_size 157 +#define wippersnapper_display_v1_I2cConfig_size 469 +#define wippersnapper_display_v1_SSD1306Config_size 14 +#define wippersnapper_display_v1_LEDBackpackConfig_size 13 +#define wippersnapper_display_v1_CharLCDConfig_size 12 +#define wippersnapper_display_v1_DisplayAddOrReplace_size 574 #define wippersnapper_display_v1_DisplayRemove_size 65 #define wippersnapper_display_v1_DisplayWrite_size 1104 #define wippersnapper_display_v1_DisplayAddedorReplaced_size 67 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index 2b844940b..691e196de 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index 84a16a5de..680d25f23 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index 9a2cd926d..48f0ce3f7 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -51,32 +51,6 @@ PB_BIND(wippersnapper_i2c_v1_SensorEvent, wippersnapper_i2c_v1_SensorEvent, AUTO PB_BIND(wippersnapper_i2c_v1_I2CDeviceEvent, wippersnapper_i2c_v1_I2CDeviceEvent, AUTO) -PB_BIND(wippersnapper_i2c_v1_I2CDeviceOutputWrite, wippersnapper_i2c_v1_I2CDeviceOutputWrite, 2) - - -PB_BIND(wippersnapper_i2c_v1_LEDBackpackConfig, wippersnapper_i2c_v1_LEDBackpackConfig, AUTO) - - -PB_BIND(wippersnapper_i2c_v1_CharLCDConfig, wippersnapper_i2c_v1_CharLCDConfig, AUTO) - - -PB_BIND(wippersnapper_i2c_v1_SSD1306Config, wippersnapper_i2c_v1_SSD1306Config, AUTO) - - -PB_BIND(wippersnapper_i2c_v1_I2COutputAdd, wippersnapper_i2c_v1_I2COutputAdd, AUTO) - - -PB_BIND(wippersnapper_i2c_v1_LEDBackpackWrite, wippersnapper_i2c_v1_LEDBackpackWrite, AUTO) - - -PB_BIND(wippersnapper_i2c_v1_CharLCDWrite, wippersnapper_i2c_v1_CharLCDWrite, AUTO) - - -PB_BIND(wippersnapper_i2c_v1_SSD1306Write, wippersnapper_i2c_v1_SSD1306Write, 2) - - - - diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 0afda161c..37ac10c02 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED @@ -60,33 +60,11 @@ typedef enum _wippersnapper_i2c_v1_SensorType { wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_TVOC = 35 } wippersnapper_i2c_v1_SensorType; -typedef enum _wippersnapper_i2c_v1_LEDBackpackAlignment { - wippersnapper_i2c_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_UNSPECIFIED = 0, - wippersnapper_i2c_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_LEFT = 1, - wippersnapper_i2c_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT = 2 -} wippersnapper_i2c_v1_LEDBackpackAlignment; - -typedef enum _wippersnapper_i2c_v1_SSD1306TextSize { - wippersnapper_i2c_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_UNSPECIFIED = 0, - wippersnapper_i2c_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_1 = 1, - wippersnapper_i2c_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_2 = 2 -} wippersnapper_i2c_v1_SSD1306TextSize; - /* Struct definitions */ typedef struct _wippersnapper_i2c_v1_I2CDeviceInitRequests { pb_callback_t list; } wippersnapper_i2c_v1_I2CDeviceInitRequests; -typedef struct _wippersnapper_i2c_v1_CharLCDConfig { - uint32_t rows; - uint32_t columns; -} wippersnapper_i2c_v1_CharLCDConfig; - -typedef struct _wippersnapper_i2c_v1_CharLCDWrite { - char message[128]; - bool enable_backlight; -} wippersnapper_i2c_v1_CharLCDWrite; - typedef struct _wippersnapper_i2c_v1_I2CBusInitRequest { int32_t i2c_pin_scl; int32_t i2c_pin_sda; @@ -134,25 +112,6 @@ typedef struct _wippersnapper_i2c_v1_I2CDeviceUpdateResponse { wippersnapper_i2c_v1_BusResponse bus_response; } wippersnapper_i2c_v1_I2CDeviceUpdateResponse; -typedef struct _wippersnapper_i2c_v1_LEDBackpackConfig { - int32_t brightness; - wippersnapper_i2c_v1_LEDBackpackAlignment alignment; -} wippersnapper_i2c_v1_LEDBackpackConfig; - -typedef struct _wippersnapper_i2c_v1_LEDBackpackWrite { - char message[128]; -} wippersnapper_i2c_v1_LEDBackpackWrite; - -typedef struct _wippersnapper_i2c_v1_SSD1306Config { - uint32_t width; - uint32_t height; - wippersnapper_i2c_v1_SSD1306TextSize text_size; -} wippersnapper_i2c_v1_SSD1306Config; - -typedef struct _wippersnapper_i2c_v1_SSD1306Write { - char message[256]; -} wippersnapper_i2c_v1_SSD1306Write; - typedef struct _wippersnapper_i2c_v1_SensorEvent { wippersnapper_i2c_v1_SensorType type; float value; @@ -170,46 +129,23 @@ typedef struct _wippersnapper_i2c_v1_I2CDeviceEvent { wippersnapper_i2c_v1_SensorEvent sensor_event[15]; } wippersnapper_i2c_v1_I2CDeviceEvent; -typedef struct _wippersnapper_i2c_v1_I2CDeviceOutputWrite { - uint32_t i2c_device_address; - char i2c_device_name[256]; - pb_size_t which_output_msg; - union { - wippersnapper_i2c_v1_LEDBackpackWrite write_led_backpack; - wippersnapper_i2c_v1_CharLCDWrite write_char_lcd; - wippersnapper_i2c_v1_SSD1306Write write_ssd1306; - } output_msg; -} wippersnapper_i2c_v1_I2CDeviceOutputWrite; - -typedef struct _wippersnapper_i2c_v1_I2CDeviceUpdateRequest { +typedef struct _wippersnapper_i2c_v1_I2CDeviceInitRequest { int32_t i2c_port_number; + bool has_i2c_bus_init_req; + wippersnapper_i2c_v1_I2CBusInitRequest i2c_bus_init_req; uint32_t i2c_device_address; char i2c_device_name[256]; pb_size_t i2c_device_properties_count; wippersnapper_i2c_v1_I2CDeviceSensorProperties i2c_device_properties[15]; -} wippersnapper_i2c_v1_I2CDeviceUpdateRequest; - -typedef struct _wippersnapper_i2c_v1_I2COutputAdd { - pb_size_t which_config; - union { - wippersnapper_i2c_v1_LEDBackpackConfig led_backpack_config; - wippersnapper_i2c_v1_CharLCDConfig char_lcd_config; - wippersnapper_i2c_v1_SSD1306Config ssd1306_config; - } config; -} wippersnapper_i2c_v1_I2COutputAdd; +} wippersnapper_i2c_v1_I2CDeviceInitRequest; -typedef struct _wippersnapper_i2c_v1_I2CDeviceInitRequest { +typedef struct _wippersnapper_i2c_v1_I2CDeviceUpdateRequest { int32_t i2c_port_number; - bool has_i2c_bus_init_req; - wippersnapper_i2c_v1_I2CBusInitRequest i2c_bus_init_req; uint32_t i2c_device_address; char i2c_device_name[256]; pb_size_t i2c_device_properties_count; wippersnapper_i2c_v1_I2CDeviceSensorProperties i2c_device_properties[15]; - bool is_output_device; - bool has_i2c_output_add; - wippersnapper_i2c_v1_I2COutputAdd i2c_output_add; -} wippersnapper_i2c_v1_I2CDeviceInitRequest; +} wippersnapper_i2c_v1_I2CDeviceUpdateRequest; /* Helper constants for enums */ @@ -221,14 +157,6 @@ typedef struct _wippersnapper_i2c_v1_I2CDeviceInitRequest { #define _wippersnapper_i2c_v1_SensorType_MAX wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_TVOC #define _wippersnapper_i2c_v1_SensorType_ARRAYSIZE ((wippersnapper_i2c_v1_SensorType)(wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_TVOC+1)) -#define _wippersnapper_i2c_v1_LEDBackpackAlignment_MIN wippersnapper_i2c_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_UNSPECIFIED -#define _wippersnapper_i2c_v1_LEDBackpackAlignment_MAX wippersnapper_i2c_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT -#define _wippersnapper_i2c_v1_LEDBackpackAlignment_ARRAYSIZE ((wippersnapper_i2c_v1_LEDBackpackAlignment)(wippersnapper_i2c_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT+1)) - -#define _wippersnapper_i2c_v1_SSD1306TextSize_MIN wippersnapper_i2c_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_UNSPECIFIED -#define _wippersnapper_i2c_v1_SSD1306TextSize_MAX wippersnapper_i2c_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_2 -#define _wippersnapper_i2c_v1_SSD1306TextSize_ARRAYSIZE ((wippersnapper_i2c_v1_SSD1306TextSize)(wippersnapper_i2c_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_2+1)) - #ifdef __cplusplus extern "C" { @@ -242,7 +170,7 @@ extern "C" { #define wippersnapper_i2c_v1_I2CBusScanResponse_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, _wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default {_wippersnapper_i2c_v1_SensorType_MIN, 0} #define wippersnapper_i2c_v1_I2CDeviceInitRequests_init_default {{{NULL}, NULL}} -#define wippersnapper_i2c_v1_I2CDeviceInitRequest_init_default {0, false, wippersnapper_i2c_v1_I2CBusInitRequest_init_default, 0, "", 0, {wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default}, 0, false, wippersnapper_i2c_v1_I2COutputAdd_init_default} +#define wippersnapper_i2c_v1_I2CDeviceInitRequest_init_default {0, false, wippersnapper_i2c_v1_I2CBusInitRequest_init_default, 0, "", 0, {wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default}} #define wippersnapper_i2c_v1_I2CDeviceInitResponse_init_default {0, _wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_init_default {0, 0, "", 0, {wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default}} #define wippersnapper_i2c_v1_I2CDeviceUpdateResponse_init_default {0, _wippersnapper_i2c_v1_BusResponse_MIN} @@ -250,14 +178,6 @@ extern "C" { #define wippersnapper_i2c_v1_I2CDeviceDeinitResponse_init_default {0, _wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_SensorEvent_init_default {_wippersnapper_i2c_v1_SensorType_MIN, 0} #define wippersnapper_i2c_v1_I2CDeviceEvent_init_default {0, 0, {wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default}} -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_init_default {0, "", 0, {wippersnapper_i2c_v1_LEDBackpackWrite_init_default}} -#define wippersnapper_i2c_v1_LEDBackpackConfig_init_default {0, _wippersnapper_i2c_v1_LEDBackpackAlignment_MIN} -#define wippersnapper_i2c_v1_CharLCDConfig_init_default {0, 0} -#define wippersnapper_i2c_v1_SSD1306Config_init_default {0, 0, _wippersnapper_i2c_v1_SSD1306TextSize_MIN} -#define wippersnapper_i2c_v1_I2COutputAdd_init_default {0, {wippersnapper_i2c_v1_LEDBackpackConfig_init_default}} -#define wippersnapper_i2c_v1_LEDBackpackWrite_init_default {""} -#define wippersnapper_i2c_v1_CharLCDWrite_init_default {"", 0} -#define wippersnapper_i2c_v1_SSD1306Write_init_default {""} #define wippersnapper_i2c_v1_I2CBusInitRequest_init_zero {0, 0, 0, 0} #define wippersnapper_i2c_v1_I2CBusInitResponse_init_zero {_wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_I2CBusSetFrequency_init_zero {0, 0} @@ -265,7 +185,7 @@ extern "C" { #define wippersnapper_i2c_v1_I2CBusScanResponse_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, _wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero {_wippersnapper_i2c_v1_SensorType_MIN, 0} #define wippersnapper_i2c_v1_I2CDeviceInitRequests_init_zero {{{NULL}, NULL}} -#define wippersnapper_i2c_v1_I2CDeviceInitRequest_init_zero {0, false, wippersnapper_i2c_v1_I2CBusInitRequest_init_zero, 0, "", 0, {wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero}, 0, false, wippersnapper_i2c_v1_I2COutputAdd_init_zero} +#define wippersnapper_i2c_v1_I2CDeviceInitRequest_init_zero {0, false, wippersnapper_i2c_v1_I2CBusInitRequest_init_zero, 0, "", 0, {wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero}} #define wippersnapper_i2c_v1_I2CDeviceInitResponse_init_zero {0, _wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_init_zero {0, 0, "", 0, {wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero}} #define wippersnapper_i2c_v1_I2CDeviceUpdateResponse_init_zero {0, _wippersnapper_i2c_v1_BusResponse_MIN} @@ -273,21 +193,9 @@ extern "C" { #define wippersnapper_i2c_v1_I2CDeviceDeinitResponse_init_zero {0, _wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_SensorEvent_init_zero {_wippersnapper_i2c_v1_SensorType_MIN, 0} #define wippersnapper_i2c_v1_I2CDeviceEvent_init_zero {0, 0, {wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero}} -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_init_zero {0, "", 0, {wippersnapper_i2c_v1_LEDBackpackWrite_init_zero}} -#define wippersnapper_i2c_v1_LEDBackpackConfig_init_zero {0, _wippersnapper_i2c_v1_LEDBackpackAlignment_MIN} -#define wippersnapper_i2c_v1_CharLCDConfig_init_zero {0, 0} -#define wippersnapper_i2c_v1_SSD1306Config_init_zero {0, 0, _wippersnapper_i2c_v1_SSD1306TextSize_MIN} -#define wippersnapper_i2c_v1_I2COutputAdd_init_zero {0, {wippersnapper_i2c_v1_LEDBackpackConfig_init_zero}} -#define wippersnapper_i2c_v1_LEDBackpackWrite_init_zero {""} -#define wippersnapper_i2c_v1_CharLCDWrite_init_zero {"", 0} -#define wippersnapper_i2c_v1_SSD1306Write_init_zero {""} /* Field tags (for use in manual encoding/decoding) */ #define wippersnapper_i2c_v1_I2CDeviceInitRequests_list_tag 1 -#define wippersnapper_i2c_v1_CharLCDConfig_rows_tag 1 -#define wippersnapper_i2c_v1_CharLCDConfig_columns_tag 2 -#define wippersnapper_i2c_v1_CharLCDWrite_message_tag 1 -#define wippersnapper_i2c_v1_CharLCDWrite_enable_backlight_tag 2 #define wippersnapper_i2c_v1_I2CBusInitRequest_i2c_pin_scl_tag 1 #define wippersnapper_i2c_v1_I2CBusInitRequest_i2c_pin_sda_tag 2 #define wippersnapper_i2c_v1_I2CBusInitRequest_i2c_frequency_tag 3 @@ -307,38 +215,21 @@ extern "C" { #define wippersnapper_i2c_v1_I2CDeviceSensorProperties_sensor_period_tag 2 #define wippersnapper_i2c_v1_I2CDeviceUpdateResponse_i2c_device_address_tag 1 #define wippersnapper_i2c_v1_I2CDeviceUpdateResponse_bus_response_tag 3 -#define wippersnapper_i2c_v1_LEDBackpackConfig_brightness_tag 1 -#define wippersnapper_i2c_v1_LEDBackpackConfig_alignment_tag 2 -#define wippersnapper_i2c_v1_LEDBackpackWrite_message_tag 1 -#define wippersnapper_i2c_v1_SSD1306Config_width_tag 1 -#define wippersnapper_i2c_v1_SSD1306Config_height_tag 2 -#define wippersnapper_i2c_v1_SSD1306Config_text_size_tag 3 -#define wippersnapper_i2c_v1_SSD1306Write_message_tag 1 #define wippersnapper_i2c_v1_SensorEvent_type_tag 1 #define wippersnapper_i2c_v1_SensorEvent_value_tag 2 #define wippersnapper_i2c_v1_I2CBusScanRequest_i2c_port_number_tag 1 #define wippersnapper_i2c_v1_I2CBusScanRequest_bus_init_request_tag 2 #define wippersnapper_i2c_v1_I2CDeviceEvent_sensor_address_tag 1 #define wippersnapper_i2c_v1_I2CDeviceEvent_sensor_event_tag 2 -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_i2c_device_address_tag 1 -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_i2c_device_name_tag 2 -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_led_backpack_tag 3 -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_char_lcd_tag 4 -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_ssd1306_tag 5 -#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_port_number_tag 1 -#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_device_address_tag 2 -#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_device_name_tag 3 -#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_device_properties_tag 4 -#define wippersnapper_i2c_v1_I2COutputAdd_led_backpack_config_tag 1 -#define wippersnapper_i2c_v1_I2COutputAdd_char_lcd_config_tag 2 -#define wippersnapper_i2c_v1_I2COutputAdd_ssd1306_config_tag 3 #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_port_number_tag 1 #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_bus_init_req_tag 2 #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_device_address_tag 3 #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_device_name_tag 4 #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_device_properties_tag 5 -#define wippersnapper_i2c_v1_I2CDeviceInitRequest_is_output_device_tag 6 -#define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_output_add_tag 7 +#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_port_number_tag 1 +#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_device_address_tag 2 +#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_device_name_tag 3 +#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_device_properties_tag 4 /* Struct field encoding specification for nanopb */ #define wippersnapper_i2c_v1_I2CBusInitRequest_FIELDLIST(X, a) \ @@ -390,14 +281,11 @@ X(a, STATIC, SINGULAR, INT32, i2c_port_number, 1) \ X(a, STATIC, OPTIONAL, MESSAGE, i2c_bus_init_req, 2) \ X(a, STATIC, SINGULAR, UINT32, i2c_device_address, 3) \ X(a, STATIC, SINGULAR, STRING, i2c_device_name, 4) \ -X(a, STATIC, REPEATED, MESSAGE, i2c_device_properties, 5) \ -X(a, STATIC, SINGULAR, BOOL, is_output_device, 6) \ -X(a, STATIC, OPTIONAL, MESSAGE, i2c_output_add, 7) +X(a, STATIC, REPEATED, MESSAGE, i2c_device_properties, 5) #define wippersnapper_i2c_v1_I2CDeviceInitRequest_CALLBACK NULL #define wippersnapper_i2c_v1_I2CDeviceInitRequest_DEFAULT NULL #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_bus_init_req_MSGTYPE wippersnapper_i2c_v1_I2CBusInitRequest #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_device_properties_MSGTYPE wippersnapper_i2c_v1_I2CDeviceSensorProperties -#define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_output_add_MSGTYPE wippersnapper_i2c_v1_I2COutputAdd #define wippersnapper_i2c_v1_I2CDeviceInitResponse_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, i2c_device_address, 2) \ @@ -445,63 +333,6 @@ X(a, STATIC, REPEATED, MESSAGE, sensor_event, 2) #define wippersnapper_i2c_v1_I2CDeviceEvent_DEFAULT NULL #define wippersnapper_i2c_v1_I2CDeviceEvent_sensor_event_MSGTYPE wippersnapper_i2c_v1_SensorEvent -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, i2c_device_address, 1) \ -X(a, STATIC, SINGULAR, STRING, i2c_device_name, 2) \ -X(a, STATIC, ONEOF, MESSAGE, (output_msg,write_led_backpack,output_msg.write_led_backpack), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (output_msg,write_char_lcd,output_msg.write_char_lcd), 4) \ -X(a, STATIC, ONEOF, MESSAGE, (output_msg,write_ssd1306,output_msg.write_ssd1306), 5) -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_CALLBACK NULL -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_DEFAULT NULL -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_output_msg_write_led_backpack_MSGTYPE wippersnapper_i2c_v1_LEDBackpackWrite -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_output_msg_write_char_lcd_MSGTYPE wippersnapper_i2c_v1_CharLCDWrite -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_output_msg_write_ssd1306_MSGTYPE wippersnapper_i2c_v1_SSD1306Write - -#define wippersnapper_i2c_v1_LEDBackpackConfig_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, INT32, brightness, 1) \ -X(a, STATIC, SINGULAR, UENUM, alignment, 2) -#define wippersnapper_i2c_v1_LEDBackpackConfig_CALLBACK NULL -#define wippersnapper_i2c_v1_LEDBackpackConfig_DEFAULT NULL - -#define wippersnapper_i2c_v1_CharLCDConfig_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, rows, 1) \ -X(a, STATIC, SINGULAR, UINT32, columns, 2) -#define wippersnapper_i2c_v1_CharLCDConfig_CALLBACK NULL -#define wippersnapper_i2c_v1_CharLCDConfig_DEFAULT NULL - -#define wippersnapper_i2c_v1_SSD1306Config_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, width, 1) \ -X(a, STATIC, SINGULAR, UINT32, height, 2) \ -X(a, STATIC, SINGULAR, UENUM, text_size, 3) -#define wippersnapper_i2c_v1_SSD1306Config_CALLBACK NULL -#define wippersnapper_i2c_v1_SSD1306Config_DEFAULT NULL - -#define wippersnapper_i2c_v1_I2COutputAdd_FIELDLIST(X, a) \ -X(a, STATIC, ONEOF, MESSAGE, (config,led_backpack_config,config.led_backpack_config), 1) \ -X(a, STATIC, ONEOF, MESSAGE, (config,char_lcd_config,config.char_lcd_config), 2) \ -X(a, STATIC, ONEOF, MESSAGE, (config,ssd1306_config,config.ssd1306_config), 3) -#define wippersnapper_i2c_v1_I2COutputAdd_CALLBACK NULL -#define wippersnapper_i2c_v1_I2COutputAdd_DEFAULT NULL -#define wippersnapper_i2c_v1_I2COutputAdd_config_led_backpack_config_MSGTYPE wippersnapper_i2c_v1_LEDBackpackConfig -#define wippersnapper_i2c_v1_I2COutputAdd_config_char_lcd_config_MSGTYPE wippersnapper_i2c_v1_CharLCDConfig -#define wippersnapper_i2c_v1_I2COutputAdd_config_ssd1306_config_MSGTYPE wippersnapper_i2c_v1_SSD1306Config - -#define wippersnapper_i2c_v1_LEDBackpackWrite_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, STRING, message, 1) -#define wippersnapper_i2c_v1_LEDBackpackWrite_CALLBACK NULL -#define wippersnapper_i2c_v1_LEDBackpackWrite_DEFAULT NULL - -#define wippersnapper_i2c_v1_CharLCDWrite_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, STRING, message, 1) \ -X(a, STATIC, SINGULAR, BOOL, enable_backlight, 2) -#define wippersnapper_i2c_v1_CharLCDWrite_CALLBACK NULL -#define wippersnapper_i2c_v1_CharLCDWrite_DEFAULT NULL - -#define wippersnapper_i2c_v1_SSD1306Write_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, STRING, message, 1) -#define wippersnapper_i2c_v1_SSD1306Write_CALLBACK NULL -#define wippersnapper_i2c_v1_SSD1306Write_DEFAULT NULL - extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CBusInitRequest_msg; extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CBusInitResponse_msg; extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CBusSetFrequency_msg; @@ -517,14 +348,6 @@ extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CDeviceDeinitRequest_msg; extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CDeviceDeinitResponse_msg; extern const pb_msgdesc_t wippersnapper_i2c_v1_SensorEvent_msg; extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CDeviceEvent_msg; -extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CDeviceOutputWrite_msg; -extern const pb_msgdesc_t wippersnapper_i2c_v1_LEDBackpackConfig_msg; -extern const pb_msgdesc_t wippersnapper_i2c_v1_CharLCDConfig_msg; -extern const pb_msgdesc_t wippersnapper_i2c_v1_SSD1306Config_msg; -extern const pb_msgdesc_t wippersnapper_i2c_v1_I2COutputAdd_msg; -extern const pb_msgdesc_t wippersnapper_i2c_v1_LEDBackpackWrite_msg; -extern const pb_msgdesc_t wippersnapper_i2c_v1_CharLCDWrite_msg; -extern const pb_msgdesc_t wippersnapper_i2c_v1_SSD1306Write_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define wippersnapper_i2c_v1_I2CBusInitRequest_fields &wippersnapper_i2c_v1_I2CBusInitRequest_msg @@ -542,14 +365,6 @@ extern const pb_msgdesc_t wippersnapper_i2c_v1_SSD1306Write_msg; #define wippersnapper_i2c_v1_I2CDeviceDeinitResponse_fields &wippersnapper_i2c_v1_I2CDeviceDeinitResponse_msg #define wippersnapper_i2c_v1_SensorEvent_fields &wippersnapper_i2c_v1_SensorEvent_msg #define wippersnapper_i2c_v1_I2CDeviceEvent_fields &wippersnapper_i2c_v1_I2CDeviceEvent_msg -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_fields &wippersnapper_i2c_v1_I2CDeviceOutputWrite_msg -#define wippersnapper_i2c_v1_LEDBackpackConfig_fields &wippersnapper_i2c_v1_LEDBackpackConfig_msg -#define wippersnapper_i2c_v1_CharLCDConfig_fields &wippersnapper_i2c_v1_CharLCDConfig_msg -#define wippersnapper_i2c_v1_SSD1306Config_fields &wippersnapper_i2c_v1_SSD1306Config_msg -#define wippersnapper_i2c_v1_I2COutputAdd_fields &wippersnapper_i2c_v1_I2COutputAdd_msg -#define wippersnapper_i2c_v1_LEDBackpackWrite_fields &wippersnapper_i2c_v1_LEDBackpackWrite_msg -#define wippersnapper_i2c_v1_CharLCDWrite_fields &wippersnapper_i2c_v1_CharLCDWrite_msg -#define wippersnapper_i2c_v1_SSD1306Write_fields &wippersnapper_i2c_v1_SSD1306Write_msg /* Maximum encoded size of messages (where known) */ #define wippersnapper_i2c_v1_I2CBusInitRequest_size 39 @@ -559,7 +374,7 @@ extern const pb_msgdesc_t wippersnapper_i2c_v1_SSD1306Write_msg; #define wippersnapper_i2c_v1_I2CBusScanResponse_size 722 #define wippersnapper_i2c_v1_I2CDeviceSensorProperties_size 8 /* wippersnapper_i2c_v1_I2CDeviceInitRequests_size depends on runtime parameters */ -#define wippersnapper_i2c_v1_I2CDeviceInitRequest_size 486 +#define wippersnapper_i2c_v1_I2CDeviceInitRequest_size 466 #define wippersnapper_i2c_v1_I2CDeviceInitResponse_size 8 #define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_size 425 #define wippersnapper_i2c_v1_I2CDeviceUpdateResponse_size 8 @@ -567,14 +382,6 @@ extern const pb_msgdesc_t wippersnapper_i2c_v1_SSD1306Write_msg; #define wippersnapper_i2c_v1_I2CDeviceDeinitResponse_size 8 #define wippersnapper_i2c_v1_SensorEvent_size 7 #define wippersnapper_i2c_v1_I2CDeviceEvent_size 141 -#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_size 525 -#define wippersnapper_i2c_v1_LEDBackpackConfig_size 13 -#define wippersnapper_i2c_v1_CharLCDConfig_size 12 -#define wippersnapper_i2c_v1_SSD1306Config_size 14 -#define wippersnapper_i2c_v1_I2COutputAdd_size 16 -#define wippersnapper_i2c_v1_LEDBackpackWrite_size 130 -#define wippersnapper_i2c_v1_CharLCDWrite_size 132 -#define wippersnapper_i2c_v1_SSD1306Write_size 258 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 87af9a92e..7ecae5f2a 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index 3c9d51238..9ee2a6286 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index a7fb45322..d20cfe3ff 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index 65c3de75a..92c2c0261 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index 7cfdd2901..4b2ac1ebb 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index e3cdf3439..b0e892a98 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index 7431b6661..9818abdfd 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index 063a04554..f92d0c55f 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index ac1d37b30..19053eabd 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 1939d6407..60641e0c9 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED @@ -76,7 +76,6 @@ typedef struct _wippersnapper_signal_v1_I2CRequest { wippersnapper_i2c_v1_I2CDeviceDeinitRequest req_i2c_device_deinit; wippersnapper_i2c_v1_I2CDeviceUpdateRequest req_i2c_device_update; wippersnapper_i2c_v1_I2CDeviceInitRequests req_i2c_device_init_requests; - wippersnapper_i2c_v1_I2CDeviceOutputWrite req_i2c_device_out_write; } payload; } wippersnapper_signal_v1_I2CRequest; @@ -231,7 +230,6 @@ extern "C" { #define wippersnapper_signal_v1_I2CRequest_req_i2c_device_deinit_tag 5 #define wippersnapper_signal_v1_I2CRequest_req_i2c_device_update_tag 6 #define wippersnapper_signal_v1_I2CRequest_req_i2c_device_init_requests_tag 7 -#define wippersnapper_signal_v1_I2CRequest_req_i2c_device_out_write_tag 8 #define wippersnapper_signal_v1_I2CResponse_resp_i2c_scan_tag 2 #define wippersnapper_signal_v1_I2CResponse_resp_i2c_device_init_tag 3 #define wippersnapper_signal_v1_I2CResponse_resp_i2c_device_deinit_tag 4 @@ -296,8 +294,7 @@ X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_set_freq,payload.req_i2c_set X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_init,payload.req_i2c_device_init), 4) \ X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_deinit,payload.req_i2c_device_deinit), 5) \ X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_update,payload.req_i2c_device_update), 6) \ -X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_init_requests,payload.req_i2c_device_init_requests), 7) \ -X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_out_write,payload.req_i2c_device_out_write), 8) +X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_init_requests,payload.req_i2c_device_init_requests), 7) #define wippersnapper_signal_v1_I2CRequest_CALLBACK NULL #define wippersnapper_signal_v1_I2CRequest_DEFAULT NULL #define wippersnapper_signal_v1_I2CRequest_payload_req_i2c_scan_MSGTYPE wippersnapper_i2c_v1_I2CBusScanRequest @@ -306,7 +303,6 @@ X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_out_write,payload.req #define wippersnapper_signal_v1_I2CRequest_payload_req_i2c_device_deinit_MSGTYPE wippersnapper_i2c_v1_I2CDeviceDeinitRequest #define wippersnapper_signal_v1_I2CRequest_payload_req_i2c_device_update_MSGTYPE wippersnapper_i2c_v1_I2CDeviceUpdateRequest #define wippersnapper_signal_v1_I2CRequest_payload_req_i2c_device_init_requests_MSGTYPE wippersnapper_i2c_v1_I2CDeviceInitRequests -#define wippersnapper_signal_v1_I2CRequest_payload_req_i2c_device_out_write_MSGTYPE wippersnapper_i2c_v1_I2CDeviceOutputWrite #define wippersnapper_signal_v1_I2CResponse_FIELDLIST(X, a) \ X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_i2c_scan,payload.resp_i2c_scan), 2) \ @@ -448,7 +444,7 @@ extern const pb_msgdesc_t wippersnapper_signal_v1_DisplayResponse_msg; #define wippersnapper_signal_v1_Ds18x20Request_size 39 #define wippersnapper_signal_v1_Ds18x20Response_size 26 #if defined(wippersnapper_i2c_v1_I2CDeviceInitRequests_size) -union wippersnapper_signal_v1_I2CRequest_payload_size_union {char f7[(6 + wippersnapper_i2c_v1_I2CDeviceInitRequests_size)]; char f0[528];}; +union wippersnapper_signal_v1_I2CRequest_payload_size_union {char f7[(6 + wippersnapper_i2c_v1_I2CDeviceInitRequests_size)]; char f0[469];}; #define wippersnapper_signal_v1_I2CRequest_size (0 + sizeof(union wippersnapper_signal_v1_I2CRequest_payload_size_union)) #endif #define wippersnapper_signal_v1_I2CResponse_size 725 diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index 2f7925a88..22b822799 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index 101d5bb60..e70dce8b6 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From 9c34298b8cbf5f464c98c3b393210f1567e4f34c Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 4 Sep 2025 15:41:08 -0400 Subject: [PATCH 46/76] Match 6eae897..1065c87 --- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 4 +- src/wippersnapper/display/v1/display.pb.h | 40 +++++++++---------- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 2 +- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 20 files changed, 40 insertions(+), 40 deletions(-) diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index 5e84e10ff..5bc4cd201 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index e1ceb5aad..303f97b77 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 08385fe52..0bb609fb2 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -21,7 +21,7 @@ PB_BIND(wippersnapper_display_v1_TftConfig, wippersnapper_display_v1_TftConfig, PB_BIND(wippersnapper_display_v1_I2cConfig, wippersnapper_display_v1_I2cConfig, 2) -PB_BIND(wippersnapper_display_v1_SSD1306Config, wippersnapper_display_v1_SSD1306Config, AUTO) +PB_BIND(wippersnapper_display_v1_OledConfig, wippersnapper_display_v1_OledConfig, AUTO) PB_BIND(wippersnapper_display_v1_LEDBackpackConfig, wippersnapper_display_v1_LEDBackpackConfig, AUTO) diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index ba8c3675f..132bf5f8a 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -75,11 +75,11 @@ typedef struct _wippersnapper_display_v1_LEDBackpackConfig { wippersnapper_display_v1_LEDBackpackAlignment alignment; } wippersnapper_display_v1_LEDBackpackConfig; -typedef struct _wippersnapper_display_v1_SSD1306Config { +typedef struct _wippersnapper_display_v1_OledConfig { uint32_t width; uint32_t height; - wippersnapper_display_v1_SSD1306TextSize text_size; -} wippersnapper_display_v1_SSD1306Config; + int32_t text_size; +} wippersnapper_display_v1_OledConfig; typedef struct _wippersnapper_display_v1_SpiConfig { int32_t bus; @@ -111,7 +111,7 @@ typedef struct _wippersnapper_display_v1_DisplayAddOrReplace { union { wippersnapper_display_v1_EPDConfig config_epd; wippersnapper_display_v1_TftConfig config_tft; - wippersnapper_display_v1_SSD1306Config config_ssd1306; + wippersnapper_display_v1_OledConfig config_oled; wippersnapper_display_v1_LEDBackpackConfig config_led_backpack; wippersnapper_display_v1_CharLCDConfig config_char_lcd; } config; @@ -155,7 +155,7 @@ extern "C" { #define wippersnapper_display_v1_EPDWriteOptions_init_default {0} #define wippersnapper_display_v1_TftConfig_init_default {0, 0, 0} #define wippersnapper_display_v1_I2cConfig_init_default {false, wippersnapper_i2c_v1_I2CDeviceInitRequest_init_default} -#define wippersnapper_display_v1_SSD1306Config_init_default {0, 0, _wippersnapper_display_v1_SSD1306TextSize_MIN} +#define wippersnapper_display_v1_OledConfig_init_default {0, 0, 0} #define wippersnapper_display_v1_LEDBackpackConfig_init_default {0, _wippersnapper_display_v1_LEDBackpackAlignment_MIN} #define wippersnapper_display_v1_CharLCDConfig_init_default {0, 0} #define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_SpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} @@ -168,7 +168,7 @@ extern "C" { #define wippersnapper_display_v1_EPDWriteOptions_init_zero {0} #define wippersnapper_display_v1_TftConfig_init_zero {0, 0, 0} #define wippersnapper_display_v1_I2cConfig_init_zero {false, wippersnapper_i2c_v1_I2CDeviceInitRequest_init_zero} -#define wippersnapper_display_v1_SSD1306Config_init_zero {0, 0, _wippersnapper_display_v1_SSD1306TextSize_MIN} +#define wippersnapper_display_v1_OledConfig_init_zero {0, 0, 0} #define wippersnapper_display_v1_LEDBackpackConfig_init_zero {0, _wippersnapper_display_v1_LEDBackpackAlignment_MIN} #define wippersnapper_display_v1_CharLCDConfig_init_zero {0, 0} #define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_SpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} @@ -190,9 +190,9 @@ extern "C" { #define wippersnapper_display_v1_I2cConfig_i2c_tag 1 #define wippersnapper_display_v1_LEDBackpackConfig_brightness_tag 1 #define wippersnapper_display_v1_LEDBackpackConfig_alignment_tag 2 -#define wippersnapper_display_v1_SSD1306Config_width_tag 1 -#define wippersnapper_display_v1_SSD1306Config_height_tag 2 -#define wippersnapper_display_v1_SSD1306Config_text_size_tag 3 +#define wippersnapper_display_v1_OledConfig_width_tag 1 +#define wippersnapper_display_v1_OledConfig_height_tag 2 +#define wippersnapper_display_v1_OledConfig_text_size_tag 3 #define wippersnapper_display_v1_SpiConfig_bus_tag 1 #define wippersnapper_display_v1_SpiConfig_pin_dc_tag 2 #define wippersnapper_display_v1_SpiConfig_pin_rst_tag 3 @@ -211,7 +211,7 @@ extern "C" { #define wippersnapper_display_v1_DisplayAddOrReplace_cfg_i2c_tag 4 #define wippersnapper_display_v1_DisplayAddOrReplace_config_epd_tag 5 #define wippersnapper_display_v1_DisplayAddOrReplace_config_tft_tag 6 -#define wippersnapper_display_v1_DisplayAddOrReplace_config_ssd1306_tag 7 +#define wippersnapper_display_v1_DisplayAddOrReplace_config_oled_tag 7 #define wippersnapper_display_v1_DisplayAddOrReplace_config_led_backpack_tag 8 #define wippersnapper_display_v1_DisplayAddOrReplace_config_char_lcd_tag 9 #define wippersnapper_display_v1_DisplayWrite_name_tag 1 @@ -255,12 +255,12 @@ X(a, STATIC, OPTIONAL, MESSAGE, i2c, 1) #define wippersnapper_display_v1_I2cConfig_DEFAULT NULL #define wippersnapper_display_v1_I2cConfig_i2c_MSGTYPE wippersnapper_i2c_v1_I2CDeviceInitRequest -#define wippersnapper_display_v1_SSD1306Config_FIELDLIST(X, a) \ +#define wippersnapper_display_v1_OledConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, width, 1) \ X(a, STATIC, SINGULAR, UINT32, height, 2) \ -X(a, STATIC, SINGULAR, UENUM, text_size, 3) -#define wippersnapper_display_v1_SSD1306Config_CALLBACK NULL -#define wippersnapper_display_v1_SSD1306Config_DEFAULT NULL +X(a, STATIC, SINGULAR, INT32, text_size, 3) +#define wippersnapper_display_v1_OledConfig_CALLBACK NULL +#define wippersnapper_display_v1_OledConfig_DEFAULT NULL #define wippersnapper_display_v1_LEDBackpackConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, brightness, 1) \ @@ -281,7 +281,7 @@ X(a, STATIC, ONEOF, MESSAGE, (interface_type,cfg_spi,interface_type.cfg_sp X(a, STATIC, ONEOF, MESSAGE, (interface_type,cfg_i2c,interface_type.cfg_i2c), 4) \ X(a, STATIC, ONEOF, MESSAGE, (config,config_epd,config.config_epd), 5) \ X(a, STATIC, ONEOF, MESSAGE, (config,config_tft,config.config_tft), 6) \ -X(a, STATIC, ONEOF, MESSAGE, (config,config_ssd1306,config.config_ssd1306), 7) \ +X(a, STATIC, ONEOF, MESSAGE, (config,config_oled,config.config_oled), 7) \ X(a, STATIC, ONEOF, MESSAGE, (config,config_led_backpack,config.config_led_backpack), 8) \ X(a, STATIC, ONEOF, MESSAGE, (config,config_char_lcd,config.config_char_lcd), 9) #define wippersnapper_display_v1_DisplayAddOrReplace_CALLBACK NULL @@ -290,7 +290,7 @@ X(a, STATIC, ONEOF, MESSAGE, (config,config_char_lcd,config.config_char_lc #define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_cfg_i2c_MSGTYPE wippersnapper_display_v1_I2cConfig #define wippersnapper_display_v1_DisplayAddOrReplace_config_config_epd_MSGTYPE wippersnapper_display_v1_EPDConfig #define wippersnapper_display_v1_DisplayAddOrReplace_config_config_tft_MSGTYPE wippersnapper_display_v1_TftConfig -#define wippersnapper_display_v1_DisplayAddOrReplace_config_config_ssd1306_MSGTYPE wippersnapper_display_v1_SSD1306Config +#define wippersnapper_display_v1_DisplayAddOrReplace_config_config_oled_MSGTYPE wippersnapper_display_v1_OledConfig #define wippersnapper_display_v1_DisplayAddOrReplace_config_config_led_backpack_MSGTYPE wippersnapper_display_v1_LEDBackpackConfig #define wippersnapper_display_v1_DisplayAddOrReplace_config_config_char_lcd_MSGTYPE wippersnapper_display_v1_CharLCDConfig @@ -324,7 +324,7 @@ extern const pb_msgdesc_t wippersnapper_display_v1_EPDConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_EPDWriteOptions_msg; extern const pb_msgdesc_t wippersnapper_display_v1_TftConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_I2cConfig_msg; -extern const pb_msgdesc_t wippersnapper_display_v1_SSD1306Config_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_OledConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_LEDBackpackConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_CharLCDConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayAddOrReplace_msg; @@ -339,7 +339,7 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; #define wippersnapper_display_v1_EPDWriteOptions_fields &wippersnapper_display_v1_EPDWriteOptions_msg #define wippersnapper_display_v1_TftConfig_fields &wippersnapper_display_v1_TftConfig_msg #define wippersnapper_display_v1_I2cConfig_fields &wippersnapper_display_v1_I2cConfig_msg -#define wippersnapper_display_v1_SSD1306Config_fields &wippersnapper_display_v1_SSD1306Config_msg +#define wippersnapper_display_v1_OledConfig_fields &wippersnapper_display_v1_OledConfig_msg #define wippersnapper_display_v1_LEDBackpackConfig_fields &wippersnapper_display_v1_LEDBackpackConfig_msg #define wippersnapper_display_v1_CharLCDConfig_fields &wippersnapper_display_v1_CharLCDConfig_msg #define wippersnapper_display_v1_DisplayAddOrReplace_fields &wippersnapper_display_v1_DisplayAddOrReplace_msg @@ -354,7 +354,7 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; #define wippersnapper_display_v1_EPDWriteOptions_size 11 #define wippersnapper_display_v1_TftConfig_size 33 #define wippersnapper_display_v1_I2cConfig_size 469 -#define wippersnapper_display_v1_SSD1306Config_size 14 +#define wippersnapper_display_v1_OledConfig_size 23 #define wippersnapper_display_v1_LEDBackpackConfig_size 13 #define wippersnapper_display_v1_CharLCDConfig_size 12 #define wippersnapper_display_v1_DisplayAddOrReplace_size 574 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index 691e196de..9ab21fae3 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index 680d25f23..2aff24114 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index 48f0ce3f7..dc168cef1 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 37ac10c02..19dc76775 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 7ecae5f2a..044ce4f78 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index 9ee2a6286..57ec81b59 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index d20cfe3ff..58019d09f 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index 92c2c0261..cc3eba3a4 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index 4b2ac1ebb..ea30133d8 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index b0e892a98..d81176ace 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index 9818abdfd..0d49bd2e9 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index f92d0c55f..6730170ee 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index 19053eabd..a397af982 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 60641e0c9..5188be054 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index 22b822799..53ed40a0d 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index e70dce8b6..accaf7252 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 15:24:18 2025. */ +/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From bd2ce409361ff10548d8a66d8a56ebaa7226303d Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 4 Sep 2025 15:59:48 -0400 Subject: [PATCH 47/76] Add driver for sh1107, not hooked into hw yet --- src/components/display/controller.cpp | 4 +- src/components/display/drivers/dispDrvBase.h | 2 +- .../display/drivers/dispDrvSh1107.h | 171 ++++++++++++++++++ .../display/drivers/dispDrvSsd1306.h | 2 - src/components/display/hardware.cpp | 9 +- src/components/display/hardware.h | 3 +- 6 files changed, 181 insertions(+), 10 deletions(-) create mode 100644 src/components/display/drivers/dispDrvSh1107.h diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 67c0ad975..b13e9a5f0 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -57,8 +57,8 @@ bool DisplayController::Handle_Display_AddOrReplace( did_begin = display->beginTft(&msgAdd->config.config_tft, &msgAdd->interface_type.cfg_spi); } else if (msgAdd->which_config == - wippersnapper_display_v1_DisplayAddOrReplace_config_ssd1306_tag) { - did_begin = display->beginOled(&msgAdd->config.config_ssd1306, + wippersnapper_display_v1_DisplayAddOrReplace_config_oled_tag) { + did_begin = display->beginOled(&msgAdd->config.config_oled, &msgAdd->interface_type.cfg_i2c); } else if ( msgAdd->which_config == diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index ead3a3f19..ada408851 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -125,7 +125,7 @@ class dispDrvBase { @param r The rotation of the display (0-3). */ - void setRotation(uint8_t r) { _rotation = r; } + virtual void setRotation(uint8_t r) { _rotation = r; } /*! @brief Sets the text size for the display. diff --git a/src/components/display/drivers/dispDrvSh1107.h b/src/components/display/drivers/dispDrvSh1107.h new file mode 100644 index 000000000..42fbce33b --- /dev/null +++ b/src/components/display/drivers/dispDrvSh1107.h @@ -0,0 +1,171 @@ +/*! + * @file src/components/display/drivers/dispDrvSh1107.h + * + * Device driver for a SH1107 OLED Display + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Tyeth Gundry for Adafruit Industries 2025 + * + * MIT license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DISP_DRV_SH1107_H +#define WS_DISP_DRV_SH1107_H + +#include "dispDrvBase.h" +#include + +#define WS_SH1107_DEFAULT_WIDTH \ + 128 ///< Default width for a sh1107 128x64 display +#define WS_SH1107_DEFAULT_HEIGHT \ + 64 ///< Default height for a sh1107 128x64 display + +#define OLED_128X64_WING_WIDTH 128 ///< Width of the 128x64 OLED FeatherWing +#define OLED_128X64_WING_HEIGHT 64 ///< Height of the 128x64 OLED FeatherWing +#define OLED_128X64_WING_ROTATION_90 1 ///< Rotation of OLED FeatherWing 0-3 + +/*! + @brief Class that provides a driver interface for a SH1107 + OLED Display +*/ +class dispDrvSh1107 : public dispDrvBase { +public: + /*! + @brief Constructor for the SH1107 display driver. + */ + dispDrvSh1107(TwoWire *i2c, uint16_t sensorAddress) + : dispDrvBase(i2c, sensorAddress), _display(nullptr) { + _i2c = i2c; + _sensorAddress = sensorAddress; + _width = WS_SH1107_DEFAULT_WIDTH; + _height = WS_SH1107_DEFAULT_HEIGHT; + } + + /*! + @brief Destructor for a SH1107 display driver. + */ + ~dispDrvSh1107() { + if (_display != nullptr) { + _display->clearDisplay(); + _display->display(); + _display->oled_command(SH110X_DISPLAYOFF); + delete _display; + _display = nullptr; + } + } + + /*! + @brief Attempts to initialize the SSD1306 display driver. + @return True if the display was initialized successfully, false otherwise. + */ + bool begin() override { + if (!_i2c) + return false; + + // Attempt to create and allocate a SH1107 obj. + if (_width == OLED_128X64_WING_WIDTH && + _height == OLED_128X64_WING_HEIGHT && + _rotation == OLED_128X64_WING_ROTATION_90) { + // FeatherWing needs to be rotated 90deg and swap w/h ctor args + _display = new Adafruit_SH1107(_height, _width, _i2c); + } else { + _display = new Adafruit_SH1107(_width, _height, _i2c); + } + if (!_display->begin(_sensorAddress, true)) + return false; + + // Clear the buffer. + _display->clearDisplay(); + _display->display(); + _display->setRotation(_rotation); // 0-3, not degrees for SH1107 + + // Configure the text size and color + _display->setTextSize(_text_sz); + _display->setTextColor(SH110X_WHITE); + _display->setCursor(0, 0); + // Clear the buffer + _display->clearDisplay(); + _display->display(); + return true; + } + + /*! + @brief Sets the text size for the display. + @param s + The text size to set. + @note This method overrides the base class method to provide specific + functionality for the SSD1306 driver. + */ + void setTextSize(uint8_t s) override { + if (!_display) + return; + _text_sz = s; + _display->setTextSize(s); + } + + void setRotation(uint8_t r) override { + if (!_display) + return; + _rotation = r % 90; // constrain to 0-3 + _display->setRotation(r); + } + + /*! + @brief Writes a message to the display. + @param message + The message to write to the display. + @note This method overrides the base class method to provide specific + functionality for the SSD1306 driver. + */ + virtual void writeMessage(const char *message) override { + if (_display == nullptr) + return; + // Start with a fresh display buffer + // and settings + int16_t y_idx = 0; + _display->clearDisplay(); + _display->setTextSize(_text_sz); + _display->setTextColor(SH110X_WHITE); + _display->setCursor(0, y_idx); + _display->display(); + + // Calculate the line height based on the text size (NOTE: base height is + // 8px) + int16_t line_height = 8 * _text_sz; + uint16_t c_idx = 0; + size_t msg_size = strlen(message); + for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) { + if (message[i] == '\\' && i + 1 < msg_size && + (message[i + 1] == 'n' || message[i + 1] == 'r')) { + // Handle \r\n sequence as a single newline + if (message[i + 1] == 'r' && i + 3 < msg_size && + message[i + 2] == '\\' && message[i + 3] == 'n') { + // Skip to the next line + y_idx += line_height; + _display->setCursor(0, y_idx); + i += 3; + } else if (message[i + 1] == 'n') { + // Skip to the next line + y_idx += line_height; + _display->setCursor(0, y_idx); + i++; + } + } else if (message[i] == 0xC2 && message[i + 1] == 0xB0) { + _display->write(char(248)); + _display->display(); + i++; + } else { + _display->print(message[i]); + _display->display(); + } + } + } + +private: + Adafruit_SH1107 *_display; +}; + +#endif // WS_DISP_DRV_SSD1306 \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvSsd1306.h b/src/components/display/drivers/dispDrvSsd1306.h index d5df9297a..5fccafd06 100644 --- a/src/components/display/drivers/dispDrvSsd1306.h +++ b/src/components/display/drivers/dispDrvSsd1306.h @@ -102,8 +102,6 @@ class dispDrvSsd1306 : public dispDrvBase { // and settings int16_t y_idx = 0; _display->clearDisplay(); - _display->setTextSize(_text_sz); - _display->setTextColor(SSD1306_WHITE); _display->setCursor(0, y_idx); _display->display(); diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index c1d4ad79d..0071968fb 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -336,11 +336,11 @@ bool DisplayHardware::beginTft(wippersnapper_display_v1_TftConfig *config, @param config Pointer to the OLED's configuration structure. @param i2c_config - Pointer to the I2C configuration structure for OLED. + Pointer to the I2C configuration structure. @return True if configuration was successful, False otherwise. */ bool DisplayHardware::beginOled( - wippersnapper_display_v1_SSD1306Config *config, + wippersnapper_display_v1_OledConfig *config, wippersnapper_display_v1_I2cConfig *i2c_config) { // Validate pointers if (config == nullptr || i2c_config == nullptr || !i2c_config->has_i2c) { @@ -355,6 +355,7 @@ bool DisplayHardware::beginOled( _drvDisp = nullptr; } + // Initialize OLED display driver based on device name if (strnlen(i2c_config->i2c.i2c_device_name, sizeof(i2c_config->i2c.i2c_device_name)) < sizeof(i2c_config->i2c.i2c_device_name) && @@ -376,8 +377,7 @@ bool DisplayHardware::beginOled( // Configure display dimensions and text size _drvDisp->setWidth(config->width); _drvDisp->setHeight(config->height); - // tODO: Remove the ssd-1306 -specic text size setters - // _drvDisp->setTextSize(config->text_size); + _drvDisp->setTextSize(config->text_size); // Initialize the display driver if (!_drvDisp->begin()) { @@ -387,6 +387,7 @@ bool DisplayHardware::beginOled( return false; } + WS_DEBUG_PRINTLN("[display] OLED initialized successfully."); return true; } diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 42bb3ce72..2e524b3c4 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -16,6 +16,7 @@ #define WS_DISPLAY_HARDWARE_H #include "Wippersnapper.h" #include "drivers/dispDrvBase.h" +#include "drivers/dispDrvSh1107.h" #include "drivers/dispDrvSsd1306.h" #include "drivers/dispDrvSt7789.h" #include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h" @@ -44,7 +45,7 @@ class DisplayHardware { wippersnapper_display_v1_SpiConfig *spi_config); bool beginTft(wippersnapper_display_v1_TftConfig *config, wippersnapper_display_v1_SpiConfig *spi_config); - bool beginOled(wippersnapper_display_v1_SSD1306Config *config, + bool beginOled(wippersnapper_display_v1_OledConfig *config, wippersnapper_display_v1_I2cConfig *i2c_config); // From 80800eeb9593fd6898806f8bc76c5af4ec45b48a Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 4 Sep 2025 16:45:13 -0400 Subject: [PATCH 48/76] hook --- src/components/display/hardware.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 0071968fb..f39c49fe1 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -362,6 +362,11 @@ bool DisplayHardware::beginOled( strcmp(i2c_config->i2c.i2c_device_name, "SSD1306") == 0) { _drvDisp = new dispDrvSsd1306(WS._i2cPort0->getBus(), i2c_config->i2c.i2c_device_address); + } else if (strnlen(i2c_config->i2c.i2c_device_name, + sizeof(i2c_config->i2c.i2c_device_name)) < + sizeof(i2c_config->i2c.i2c_device_name) && + strcmp(i2c_config->i2c.i2c_device_name, "SH1107") == 0) { + _drvDisp = new dispDrvSh1107(WS._i2cPort0->getBus(), i2c_config->i2c.i2c_device_address); } else { WS_DEBUG_PRINTLN("[display] Unsupported OLED driver!"); return false; From f601d4d6b954f6b7e59e3b813c779b6964b685ea Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 5 Sep 2025 11:11:38 -0400 Subject: [PATCH 49/76] Add driver for 7seg --- src/components/display/drivers/dispDrv7Seg.h | 165 ++++++++++++++++++ src/components/display/drivers/dispDrvBase.h | 46 +++-- .../display/drivers/dispDrvSsd1306.h | 14 +- src/components/display/hardware.cpp | 58 +++++- src/components/display/hardware.h | 2 + .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 4 +- src/wippersnapper/display/v1/display.pb.h | 32 +--- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 2 +- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 25 files changed, 289 insertions(+), 68 deletions(-) create mode 100644 src/components/display/drivers/dispDrv7Seg.h diff --git a/src/components/display/drivers/dispDrv7Seg.h b/src/components/display/drivers/dispDrv7Seg.h new file mode 100644 index 000000000..d06d9d6ff --- /dev/null +++ b/src/components/display/drivers/dispDrv7Seg.h @@ -0,0 +1,165 @@ +/*! + * @file src/components/display/drivers/dispDrv7Seg.h + * + * Driver for 7-Segment LED Backpack displays. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DISP_DRV_7Seg +#define WS_DISP_DRV_7Seg + +#include "dispDrvBase.h" +#include + +#define LED_BACKPACK_ALIGNMENT_UNSPECIFIED 0 ///< Unspecified alignment +#define LED_BACKPACK_ALIGNMENT_LEFT 1 ///< Left alignment +#define LED_BACKPACK_ALIGNMENT_RIGHT 2 ///< Right alignment +#define LED_BACKPACK_ALIGNMENT_DEFAULT \ + LED_BACKPACK_ALIGNMENT_LEFT ///< Default alignment +#define LED_MAX_CHARS \ + 5 ///< Maximum characters for 7-segment display, including ':' +#define LED_BACKPACK_DEGREE_SYMBOL \ + 0b01100011 ///< Degree symbol for 7-segment display + +/*! + @brief Driver for 7-segment LED backpack displays. +*/ +class dispDrv7Seg : public dispDrvBase { +public: + /*! + @brief Constructor for the 7-segment LED matrix. + */ + dispDrv7Seg(TwoWire *i2c, uint16_t sensorAddress) + : dispDrvBase(i2c, sensorAddress), _matrix(nullptr) { + _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; + } + + /*! + @brief Destructor for the 7-segment LED backpack driver. + */ + ~dispDrv7Seg() { + if (_matrix) { + delete _matrix; + _matrix = nullptr; + } + } + + /*! + @brief Attempts to initialize the 7-segment LED backpack driver. + @return True if the matrix was initialized successfully, false otherwise. + */ + bool begin() override { + _matrix = new Adafruit_7segment(); + return _matrix->begin(_sensorAddress, _i2c); + } + + /*! + @brief Sets the text alignment for the matrix. + @param alignment + The desired alignment to set (LEFT or RIGHT). + */ + void setAlignment(uint32_t alignment) override { + if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) { + _alignment = LED_BACKPACK_ALIGNMENT_RIGHT; + } else { + _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; + } + } + + /*! + @brief Writes the first four characters of a message to the Adafruit + 7-segment LED matrix. + @param message + The message to be displayed. + */ + void writeMessage(const char *message) override { + if (_matrix == nullptr || message == nullptr) { + return; + } + + // Clear before writing + _matrix->clear(); + + // Calculate the number of characters to display + size_t len_display = min(strlen(message), (size_t)LED_MAX_CHARS); + + // Set the starting position based on alignment + int pos_start; + if (_alignment == LED_BACKPACK_ALIGNMENT_LEFT) { + pos_start = 0; // start at the leftmost position of the display + } else { + // Exclude decimal points from the character count because those get + // displayed on a "special" segment of the LED display + int seg_chars = 0; + for (size_t i = 0; i < len_display; i++) { + if (message[i] != '.') { + seg_chars++; + } + } + // start at the rightmost position of the display + switch (seg_chars) { + case 4: + pos_start = 0; + break; + case 3: + pos_start = 1; + break; + case 2: + pos_start = 3; // if 2 characters, start at position 3 is required + // because ':' is position 2 and we need to skip it + break; + case 1: + pos_start = 4; + break; + default: + pos_start = 0; // if no characters or overflow, start at position 0 + break; + } + } + + // Write to the display's buffer + int cur_idx = pos_start; + for (size_t i = 0; i < len_display; i++) { + + // skip position 2 + if (cur_idx == 2) { + cur_idx++; + } + // Save the character because if there's a decimal, we need to skip it in + // the buffer + char ch = message[i]; + + // Look-ahead for a decimal point to attach to the current character + bool display_dot = false; + if (i + 1 < len_display && message[i + 1] == '.') { + display_dot = true; + i++; + len_display++; + } else if (message[i] == 0xC2 && message[i + 1] == 0xB0 && + i + 1 < strlen(message)) { + // Write degree symbol + _matrix->writeDigitRaw(cur_idx, LED_BACKPACK_DEGREE_SYMBOL); + i++; + cur_idx++; + continue; // skip to next character + } + // Write the character to the display buffer + _matrix->writeDigitAscii(cur_idx, ch, display_dot); + cur_idx++; + } + // Issue the buffered data in RAM to the display + _matrix->writeDisplay(); + } + +private: + Adafruit_7segment *_matrix; +}; + +#endif // WS_DISP_DRV_7Seg \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index ada408851..5cb7bc0d2 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -63,7 +63,6 @@ class dispDrvBase { : _pin_cs(cs), _pin_dc(dc), _pin_mosi(mosi), _pin_sck(sck), _pin_rst(rst), _pin_miso(miso) {} - /*! @brief Creates a new I2C output component driver. @param i2c @@ -136,21 +135,42 @@ class dispDrvBase { */ virtual void setTextSize(uint8_t s) { _text_sz = s; } + /*! + @brief Sets the brightness for the display (if supported). + @param brightness + The brightness level to set. + @note This method can be overridden by derived classes to provide + specific functionality. + */ + virtual void setBrightness(int32_t brightness) { _brightness = brightness; } + + /*! + @brief Sets the alignment for the display (if supported). + @param alignment + The alignment to set. + @note This method can be overridden by derived classes to provide + specific functionality. + */ + virtual void setAlignment(uint32_t alignment) { _alignment = alignment; } + protected: - int16_t _pin_dc; ///< Data/Command pin - int16_t _pin_rst; ///< Reset pin - int16_t _pin_cs; ///< Chip Select pin - int16_t _pin_busy; ///< Optional Busy pin - int16_t _pin_sram_cs; ///< Optional EPD SRAM chip select pin - uint16_t _pin_mosi; ///< Optional MOSI pin for SPI TFT displays - uint16_t _pin_miso; ///< Optional MISO pin for SPI TFT displays - uint16_t _pin_sck; ///< Optional SCK pin for SPI TFT displays + int16_t _pin_dc; ///< Data/Command pin + int16_t _pin_rst; ///< Reset pin + int16_t _pin_cs; ///< Chip Select pin + int16_t _pin_busy; ///< Optional Busy pin + int16_t _pin_sram_cs; ///< Optional EPD SRAM chip select pin + uint16_t _pin_mosi; ///< Optional MOSI pin for SPI TFT displays + uint16_t _pin_miso; ///< Optional MISO pin for SPI TFT displays + uint16_t _pin_sck; ///< Optional SCK pin for SPI TFT displays TwoWire *_i2c; ///< Optional pointer to the I2C driver's Wire object uint16_t _sensorAddress; ///< Optional I2C sensor address - uint8_t _text_sz = 1; ///< Text size for displaying a message - int16_t _height; ///< Height of the display - int16_t _width; ///< Width of the display - uint8_t _rotation; ///< Rotation of the display + uint8_t _text_sz = 1; ///< Optional Text size for displaying a message + int16_t _height; ///< Optional Height of the display + int16_t _width; ///< Optional Width of the display + uint8_t _rotation; ///< Optional Rotation of the display + int32_t _brightness; ///< Optional Brightness of the display (if supported) + uint32_t _alignment; ///< Optional Alignment of the display (specific to + ///< drivers like LED backpacks) }; #endif // WS_DISP_DRV_BASE_H \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvSsd1306.h b/src/components/display/drivers/dispDrvSsd1306.h index 5fccafd06..1f81ede79 100644 --- a/src/components/display/drivers/dispDrvSsd1306.h +++ b/src/components/display/drivers/dispDrvSsd1306.h @@ -16,15 +16,14 @@ #define WS_DISP_DRV_SSD1306 #include "dispDrvBase.h" -#include #include +#include #define WS_SSD1306_DEFAULT_WIDTH \ 128 ///< Default width for a ssd1306 128x64 display #define WS_SSD1306_DEFAULT_HEIGHT \ 64 ///< Default height for a ssd1306 128x64 display - /*! @brief Driver for SSD1306-based TFT displays. */ @@ -32,13 +31,18 @@ class dispDrvSsd1306 : public dispDrvBase { public: /*! @brief Constructor for the SSD1306 display driver. + @param i2c + The I2C hardware interface, default is Wire. + @param sensorAddress + The I2C sensor's unique address. */ - dispDrvSsd1306(TwoWire *i2c, uint16_t sensorAddress) : dispDrvBase(i2c, sensorAddress), _display(nullptr) { + dispDrvSsd1306(TwoWire *i2c, uint16_t sensorAddress) + : dispDrvBase(i2c, sensorAddress), _display(nullptr) { _i2c = i2c; _sensorAddress = sensorAddress; _width = WS_SSD1306_DEFAULT_WIDTH; _height = WS_SSD1306_DEFAULT_HEIGHT; - } + } ~dispDrvSsd1306() { if (_display) { @@ -135,7 +139,7 @@ class dispDrvSsd1306 : public dispDrvBase { _display->display(); } } -} + } private: Adafruit_SSD1306 *_display; diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index f39c49fe1..c5811a5d0 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -343,10 +343,8 @@ bool DisplayHardware::beginOled( wippersnapper_display_v1_OledConfig *config, wippersnapper_display_v1_I2cConfig *i2c_config) { // Validate pointers - if (config == nullptr || i2c_config == nullptr || !i2c_config->has_i2c) { - WS_DEBUG_PRINTLN("[display] OLED or I2C config is null!"); + if (config == nullptr || i2c_config == nullptr || !i2c_config->has_i2c) return false; - } // If we already have a display driver assigned to this hardware instance, // clean it up! @@ -396,6 +394,60 @@ bool DisplayHardware::beginOled( return true; } +/*! + @brief Attempts to configure and initialize an LED Backpack display + @param config + Pointer to the LED Backpack's configuration structure. + @param i2c_config + Pointer to the I2C configuration structure. + @return True if configuration was successful, False otherwise. +*/ +bool DisplayHardware::beginLedBackpack(wippersnapper_display_v1_LEDBackpackConfig *config, wippersnapper_display_v1_I2cConfig *i2c_config) { + // Validate pointers + if (config == nullptr || i2c_config == nullptr || !i2c_config->has_i2c) + return false; + + // If we already have a display driver assigned to this hardware instance, + // clean it up! + if (_drvDisp) { + delete _drvDisp; + _drvDisp = nullptr; + } + + // Initialize OLED display driver based on device name + if (strnlen(i2c_config->i2c.i2c_device_name, + sizeof(i2c_config->i2c.i2c_device_name)) < + sizeof(i2c_config->i2c.i2c_device_name) && + strcmp(i2c_config->i2c.i2c_device_name, "7seg") == 0) { + _drvDisp = new dispDrv7Seg(WS._i2cPort0->getBus(), i2c_config->i2c.i2c_device_address); + } else { + WS_DEBUG_PRINTLN("[display] Unsupported OLED driver!"); + return false; + } + + // Validate that the display driver was created successfully + if (!_drvDisp) { + WS_DEBUG_PRINTLN("[display] Failed to create display driver!"); + _drvDisp = nullptr; + return false; + } + + // Configure display dimensions and text size + _drvDisp->setAlignment(config->alignment); + _drvDisp->setBrightness(config->brightness); + + // Initialize the display driver + if (!_drvDisp->begin()) { + WS_DEBUG_PRINTLN("[display] Failed to begin driver!"); + delete _drvDisp; + _drvDisp = nullptr; + return false; + } + + WS_DEBUG_PRINTLN("[display] LED backpack initialized successfully."); + return true; +} + /*! @brief Gets the name of the display hardware instance. @return The name of the display hardware instance. diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 2e524b3c4..346a0783d 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -21,6 +21,7 @@ #include "drivers/dispDrvSt7789.h" #include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h" #include "drivers/dispDrvThinkInkGrayscale4T5.h" +#include "drivers/dispDrv7Seg.h" #include #include @@ -47,6 +48,7 @@ class DisplayHardware { wippersnapper_display_v1_SpiConfig *spi_config); bool beginOled(wippersnapper_display_v1_OledConfig *config, wippersnapper_display_v1_I2cConfig *i2c_config); + bool beginLedBackpack(wippersnapper_display_v1_LEDBackpackConfig *config, wippersnapper_display_v1_I2cConfig *i2c_config); // // API for Adafruit_GFX that abstracts hardware functionality diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index 5bc4cd201..874e06198 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index 303f97b77..bb7e4121b 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 0bb609fb2..514b94e58 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -48,5 +48,3 @@ PB_BIND(wippersnapper_display_v1_DisplayRemoved, wippersnapper_display_v1_Displa - - diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index 132bf5f8a..a01767f1a 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -25,18 +25,6 @@ typedef enum _wippersnapper_display_v1_EPDMode { wippersnapper_display_v1_EPDMode_EPD_MODE_MONO = 2 } wippersnapper_display_v1_EPDMode; -typedef enum _wippersnapper_display_v1_SSD1306TextSize { - wippersnapper_display_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_UNSPECIFIED = 0, - wippersnapper_display_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_1 = 1, - wippersnapper_display_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_2 = 2 -} wippersnapper_display_v1_SSD1306TextSize; - -typedef enum _wippersnapper_display_v1_LEDBackpackAlignment { - wippersnapper_display_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_UNSPECIFIED = 0, - wippersnapper_display_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_LEFT = 1, - wippersnapper_display_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT = 2 -} wippersnapper_display_v1_LEDBackpackAlignment; - /* Struct definitions */ typedef struct _wippersnapper_display_v1_CharLCDConfig { uint32_t rows; @@ -72,7 +60,7 @@ typedef struct _wippersnapper_display_v1_I2cConfig { typedef struct _wippersnapper_display_v1_LEDBackpackConfig { int32_t brightness; - wippersnapper_display_v1_LEDBackpackAlignment alignment; + uint32_t alignment; } wippersnapper_display_v1_LEDBackpackConfig; typedef struct _wippersnapper_display_v1_OledConfig { @@ -136,14 +124,6 @@ typedef struct _wippersnapper_display_v1_DisplayWrite { #define _wippersnapper_display_v1_EPDMode_MAX wippersnapper_display_v1_EPDMode_EPD_MODE_MONO #define _wippersnapper_display_v1_EPDMode_ARRAYSIZE ((wippersnapper_display_v1_EPDMode)(wippersnapper_display_v1_EPDMode_EPD_MODE_MONO+1)) -#define _wippersnapper_display_v1_SSD1306TextSize_MIN wippersnapper_display_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_UNSPECIFIED -#define _wippersnapper_display_v1_SSD1306TextSize_MAX wippersnapper_display_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_2 -#define _wippersnapper_display_v1_SSD1306TextSize_ARRAYSIZE ((wippersnapper_display_v1_SSD1306TextSize)(wippersnapper_display_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_2+1)) - -#define _wippersnapper_display_v1_LEDBackpackAlignment_MIN wippersnapper_display_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_UNSPECIFIED -#define _wippersnapper_display_v1_LEDBackpackAlignment_MAX wippersnapper_display_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT -#define _wippersnapper_display_v1_LEDBackpackAlignment_ARRAYSIZE ((wippersnapper_display_v1_LEDBackpackAlignment)(wippersnapper_display_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT+1)) - #ifdef __cplusplus extern "C" { @@ -156,7 +136,7 @@ extern "C" { #define wippersnapper_display_v1_TftConfig_init_default {0, 0, 0} #define wippersnapper_display_v1_I2cConfig_init_default {false, wippersnapper_i2c_v1_I2CDeviceInitRequest_init_default} #define wippersnapper_display_v1_OledConfig_init_default {0, 0, 0} -#define wippersnapper_display_v1_LEDBackpackConfig_init_default {0, _wippersnapper_display_v1_LEDBackpackAlignment_MIN} +#define wippersnapper_display_v1_LEDBackpackConfig_init_default {0, 0} #define wippersnapper_display_v1_CharLCDConfig_init_default {0, 0} #define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_SpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} #define wippersnapper_display_v1_DisplayRemove_init_default {""} @@ -169,7 +149,7 @@ extern "C" { #define wippersnapper_display_v1_TftConfig_init_zero {0, 0, 0} #define wippersnapper_display_v1_I2cConfig_init_zero {false, wippersnapper_i2c_v1_I2CDeviceInitRequest_init_zero} #define wippersnapper_display_v1_OledConfig_init_zero {0, 0, 0} -#define wippersnapper_display_v1_LEDBackpackConfig_init_zero {0, _wippersnapper_display_v1_LEDBackpackAlignment_MIN} +#define wippersnapper_display_v1_LEDBackpackConfig_init_zero {0, 0} #define wippersnapper_display_v1_CharLCDConfig_init_zero {0, 0} #define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_SpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} #define wippersnapper_display_v1_DisplayRemove_init_zero {""} @@ -264,7 +244,7 @@ X(a, STATIC, SINGULAR, INT32, text_size, 3) #define wippersnapper_display_v1_LEDBackpackConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, brightness, 1) \ -X(a, STATIC, SINGULAR, UENUM, alignment, 2) +X(a, STATIC, SINGULAR, UINT32, alignment, 2) #define wippersnapper_display_v1_LEDBackpackConfig_CALLBACK NULL #define wippersnapper_display_v1_LEDBackpackConfig_DEFAULT NULL @@ -355,7 +335,7 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; #define wippersnapper_display_v1_TftConfig_size 33 #define wippersnapper_display_v1_I2cConfig_size 469 #define wippersnapper_display_v1_OledConfig_size 23 -#define wippersnapper_display_v1_LEDBackpackConfig_size 13 +#define wippersnapper_display_v1_LEDBackpackConfig_size 17 #define wippersnapper_display_v1_CharLCDConfig_size 12 #define wippersnapper_display_v1_DisplayAddOrReplace_size 574 #define wippersnapper_display_v1_DisplayRemove_size 65 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index 9ab21fae3..ec21e3efd 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index 2aff24114..a2834afd2 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index dc168cef1..375fa72cf 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 19dc76775..6b1d7b1b3 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 044ce4f78..32a121027 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index 57ec81b59..20785706d 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index 58019d09f..916c76794 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index cc3eba3a4..ef9c24d61 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index ea30133d8..3d1a1f9cb 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index d81176ace..f66f89c53 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index 0d49bd2e9..2156a2976 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index 6730170ee..36d2f736f 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index a397af982..14b3cc63e 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 5188be054..1ab716b8f 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index 53ed40a0d..f221f6d28 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index accaf7252..67eb6911d 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Thu Sep 4 19:40:01 2025. */ +/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From 9b5da3d6ef96942d499df810049533d3fd837e36 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 5 Sep 2025 11:57:05 -0400 Subject: [PATCH 50/76] Add driver for quadalphanum --- .../display/drivers/dispDrvQuadAlphaNum.h | 161 ++++++++++++++++++ src/components/display/hardware.cpp | 16 +- src/components/display/hardware.h | 6 +- 3 files changed, 178 insertions(+), 5 deletions(-) create mode 100644 src/components/display/drivers/dispDrvQuadAlphaNum.h diff --git a/src/components/display/drivers/dispDrvQuadAlphaNum.h b/src/components/display/drivers/dispDrvQuadAlphaNum.h new file mode 100644 index 000000000..7f603d818 --- /dev/null +++ b/src/components/display/drivers/dispDrvQuadAlphaNum.h @@ -0,0 +1,161 @@ +/*! + * @file src/components/display/drivers/dispDrvQuadAlphaNum.h + * + * Driver for Quad Alphanumeric 7-Segment LED Backpack displays. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ +#ifndef WS_DISP_DRV_QUADALPHANUM +#define WS_DISP_DRV_QUADALPHANUM + +#include "dispDrvBase.h" +#include + +#define LED_BACKPACK_ALIGNMENT_UNSPECIFIED 0 ///< Unspecified alignment +#define LED_BACKPACK_ALIGNMENT_LEFT 1 ///< Left alignment +#define LED_BACKPACK_ALIGNMENT_RIGHT 2 ///< Right alignment +#define LED_BACKPACK_ALIGNMENT_DEFAULT \ + LED_BACKPACK_ALIGNMENT_LEFT ///< Default alignment +#define LED_MAX_CHARS \ + 4 ///< Maximum number of characters to display on the alphanumeric display +#define ALPHANUM_DEGREE_SYMBOL \ + 0b0000000011100011 ///< Degree symbol for alphanumeric display + +/*! + @brief Driver for Quad Alphanumeric LED matrixes. +*/ +class dispDrvQuadAlphaNum : public dispDrvBase { +public: + /*! + @brief Constructor for Quad Alphanumeric LED matrixes. + @param i2c + The I2C hardware interface, default is Wire. + @param sensorAddress + The I2C sensor's unique address. + */ + dispDrvQuadAlphaNum(TwoWire *i2c, uint16_t sensorAddress) + : dispDrvBase(i2c, sensorAddress), _alpha4(nullptr) { + _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; + } + + /*! + @brief Destructor for the 7-segment LED backpack driver. + */ + ~dispDrvQuadAlphaNum() { + if (_alpha4) { + delete _alpha4; + _alpha4 = nullptr; + } + } + + /*! + @brief Initializes the drvOutQuadAlphaNum component and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + bool begin() override { + _alpha4 = new Adafruit_AlphaNum4(); + bool did_begin = _alpha4->begin(_sensorAddress, _i2c); + _alpha4->setBrightness(_brightness); + return did_begin; + } + + /*! + @brief Sets the brightness of the LED backpack. + @param b + The brightness value, from 0 (off) to 15 (full brightness). + */ + void setBrightness(int32_t brightness) override { + if (_alpha4 == nullptr) { + return; + } + _alpha4->setBrightness(brightness); + } + + /*! + @brief Sets the alignment of the displayed text. + @param alignment + The alignment value, either LED_BACKPACK_ALIGNMENT_LEFT or + LED_BACKPACK_ALIGNMENT_RIGHT. + */ + void setAlignment(uint32_t alignment) override { + if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) { + _alignment = LED_BACKPACK_ALIGNMENT_RIGHT; + } else { + _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; + } + } + + /*! + @brief Writes the first four characters of a message to the quad + alphanumeric display. + @param message + The message to be displayed. + */ + void writeMessage(const char *message) override { + if (_alpha4 == nullptr || message == nullptr) { + return; + } + // Clear before writing + _alpha4->clear(); + + // Calculate the number of characters to display + size_t len_display = min(strlen(message), (size_t)LED_MAX_CHARS); + + // Set the starting position based on alignment + int pos_start; + if (_alignment == LED_BACKPACK_ALIGNMENT_LEFT) { + pos_start = 0; // start at the leftmost position of the display + } else { + // Exclude decimal points from the character count because those get + // displayed on a "special" segment of the LED display + int seg_chars = 0; + for (size_t i = 0; i < len_display; i++) { + if (message[i] != '.') { + seg_chars++; + } + } + // start at the rightmost position of the display + pos_start = LED_MAX_CHARS - seg_chars; + } + + // Write to the display's buffer + int cur_idx = pos_start; + for (size_t i = 0; i < len_display; i++) { + // Save the character because if there's a decimal, we need to skip it in + // the buffer + char ch = message[i]; + + // Look-ahead for a decimal point to attach to the current character + bool display_dot = false; + if (i + 1 < len_display && message[i + 1] == '.') { + display_dot = true; + i++; + len_display++; + } else if (message[i] == 0xC2 && message[i + 1] == 0xB0 && + i + 1 < strlen(message)) { + // Write the degree symbol + _alpha4->writeDigitRaw(cur_idx, ALPHANUM_DEGREE_SYMBOL); + i++; + cur_idx++; + continue; + } + // Write the character to the display buffer + _alpha4->writeDigitAscii(cur_idx, ch, display_dot); + cur_idx++; + } + // Issue the buffered data in RAM to the display + _alpha4->writeDisplay(); + } + +private: + Adafruit_AlphaNum4 *_alpha4; ///< Pointer to an Adafruit AlphaNum4 object +}; + +#endif // WS_DISP_DRV_QUADALPHANUM \ No newline at end of file diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index c5811a5d0..a564887ae 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -364,7 +364,8 @@ bool DisplayHardware::beginOled( sizeof(i2c_config->i2c.i2c_device_name)) < sizeof(i2c_config->i2c.i2c_device_name) && strcmp(i2c_config->i2c.i2c_device_name, "SH1107") == 0) { - _drvDisp = new dispDrvSh1107(WS._i2cPort0->getBus(), i2c_config->i2c.i2c_device_address); + _drvDisp = new dispDrvSh1107(WS._i2cPort0->getBus(), + i2c_config->i2c.i2c_device_address); } else { WS_DEBUG_PRINTLN("[display] Unsupported OLED driver!"); return false; @@ -402,7 +403,9 @@ bool DisplayHardware::beginOled( Pointer to the I2C configuration structure. @return True if configuration was successful, False otherwise. */ -bool DisplayHardware::beginLedBackpack(wippersnapper_display_v1_LEDBackpackConfig *config, wippersnapper_display_v1_I2cConfig *i2c_config) { +bool DisplayHardware::beginLedBackpack( + wippersnapper_display_v1_LEDBackpackConfig *config, + wippersnapper_display_v1_I2cConfig *i2c_config) { // Validate pointers if (config == nullptr || i2c_config == nullptr || !i2c_config->has_i2c) return false; @@ -419,7 +422,14 @@ bool DisplayHardware::beginLedBackpack(wippersnapper_display_v1_LEDBackpackConfi sizeof(i2c_config->i2c.i2c_device_name)) < sizeof(i2c_config->i2c.i2c_device_name) && strcmp(i2c_config->i2c.i2c_device_name, "7seg") == 0) { - _drvDisp = new dispDrv7Seg(WS._i2cPort0->getBus(), i2c_config->i2c.i2c_device_address); + _drvDisp = new dispDrv7Seg(WS._i2cPort0->getBus(), + i2c_config->i2c.i2c_device_address); + } else if (strnlen(i2c_config->i2c.i2c_device_name, + sizeof(i2c_config->i2c.i2c_device_name)) < + sizeof(i2c_config->i2c.i2c_device_name) && + strcmp(i2c_config->i2c.i2c_device_name, "quadalphanum") == 0) { + _drvDisp = new dispDrvQuadAlphaNum(WS._i2cPort0->getBus(), + i2c_config->i2c.i2c_device_address); } else { WS_DEBUG_PRINTLN("[display] Unsupported OLED driver!"); return false; diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 346a0783d..64289f825 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -15,13 +15,14 @@ #ifndef WS_DISPLAY_HARDWARE_H #define WS_DISPLAY_HARDWARE_H #include "Wippersnapper.h" +#include "drivers/dispDrv7Seg.h" #include "drivers/dispDrvBase.h" +#include "drivers/dispDrvQuadAlphaNum.h" #include "drivers/dispDrvSh1107.h" #include "drivers/dispDrvSsd1306.h" #include "drivers/dispDrvSt7789.h" #include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h" #include "drivers/dispDrvThinkInkGrayscale4T5.h" -#include "drivers/dispDrv7Seg.h" #include #include @@ -48,7 +49,8 @@ class DisplayHardware { wippersnapper_display_v1_SpiConfig *spi_config); bool beginOled(wippersnapper_display_v1_OledConfig *config, wippersnapper_display_v1_I2cConfig *i2c_config); - bool beginLedBackpack(wippersnapper_display_v1_LEDBackpackConfig *config, wippersnapper_display_v1_I2cConfig *i2c_config); + bool beginLedBackpack(wippersnapper_display_v1_LEDBackpackConfig *config, + wippersnapper_display_v1_I2cConfig *i2c_config); // // API for Adafruit_GFX that abstracts hardware functionality From 8d03bdbd5fa61c4b3c61159258eb33146507bad4 Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 5 Sep 2025 13:58:57 -0400 Subject: [PATCH 51/76] Revert all changes after bfb1d3a --- src/Wippersnapper.cpp | 19 ++ src/components/display/controller.cpp | 19 +- src/components/display/drivers/dispDrvBase.h | 60 +--- src/components/display/hardware.cpp | 137 +-------- src/components/display/hardware.h | 12 +- src/components/i2c/WipperSnapper_I2C.cpp | 263 ++++++++++++++++++ src/components/i2c/WipperSnapper_I2C.h | 21 +- .../drivers/WipperSnapper_I2C_Driver_Out.h | 145 ++++++++++ .../WipperSnapper_I2C_Driver_Out_7Seg.h} | 102 +++++-- .../WipperSnapper_I2C_Driver_Out_CharLcd.h | 163 +++++++++++ ...pperSnapper_I2C_Driver_Out_QuadAlphaNum.h} | 99 ++++--- .../WipperSnapper_I2C_Driver_Out_Sh1107.h} | 123 +++++--- .../WipperSnapper_I2C_Driver_Out_Ssd1306.h} | 102 ++++--- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 19 +- src/wippersnapper/display/v1/display.pb.h | 188 +++++-------- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 28 +- src/wippersnapper/i2c/v1/i2c.pb.h | 223 ++++++++++++++- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 10 +- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 33 files changed, 1229 insertions(+), 534 deletions(-) create mode 100644 src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out.h rename src/components/{display/drivers/dispDrv7Seg.h => i2c/drivers/WipperSnapper_I2C_Driver_Out_7Seg.h} (55%) create mode 100644 src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_CharLcd.h rename src/components/{display/drivers/dispDrvQuadAlphaNum.h => i2c/drivers/WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h} (62%) rename src/components/{display/drivers/dispDrvSh1107.h => i2c/drivers/WipperSnapper_I2C_Driver_Out_Sh1107.h} (50%) rename src/components/{display/drivers/dispDrvSsd1306.h => i2c/drivers/WipperSnapper_I2C_Driver_Out_Ssd1306.h} (51%) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 9f8662329..cb9ff1898 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -834,6 +834,25 @@ bool cbDecodeSignalRequestI2C(pb_istream_t *stream, const pb_field_t *field, if (!encodeI2CResponse(&msgi2cResponse)) { return false; } + } else if (field->tag == + wippersnapper_signal_v1_I2CRequest_req_i2c_device_out_write_tag) { + WS_DEBUG_PRINTLN("[app] I2C Device Output Write"); + // Decode stream into an I2CDeviceDeinitRequest + wippersnapper_i2c_v1_I2CDeviceOutputWrite msgDeviceWrite = + wippersnapper_i2c_v1_I2CDeviceOutputWrite_init_zero; + // Decode stream into struct, msgI2CDeviceDeinitRequest + if (!ws_pb_decode(stream, wippersnapper_i2c_v1_I2CDeviceOutputWrite_fields, + &msgDeviceWrite)) { + WS_DEBUG_PRINTLN( + "[app] ERROR: Failed decoding I2CDeviceOutputWrite message."); + return false; + } + + if (!WS._i2cPort0->Handle_I2cDeviceOutputWrite(&msgDeviceWrite)) { + WS_DEBUG_PRINTLN("[app] ERROR: Failed to write to I2C output device."); + return false; // fail out if we can't decode, we don't have a response to + // publish + } WS_DEBUG_PRINTLN("[app] I2C Device Output Write Done"); return true; // we successfully wrote to the device, this subtype has no // response to publish to IO diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index b13e9a5f0..709ef8a4f 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -51,26 +51,11 @@ bool DisplayController::Handle_Display_AddOrReplace( if (msgAdd->which_config == wippersnapper_display_v1_DisplayAddOrReplace_config_epd_tag) { did_begin = display->beginEPD(&msgAdd->config.config_epd, - &msgAdd->interface_type.cfg_spi); + &msgAdd->interface_type.spi_epd); } else if (msgAdd->which_config == wippersnapper_display_v1_DisplayAddOrReplace_config_tft_tag) { did_begin = display->beginTft(&msgAdd->config.config_tft, - &msgAdd->interface_type.cfg_spi); - } else if (msgAdd->which_config == - wippersnapper_display_v1_DisplayAddOrReplace_config_oled_tag) { - did_begin = display->beginOled(&msgAdd->config.config_oled, - &msgAdd->interface_type.cfg_i2c); - } else if ( - msgAdd->which_config == - wippersnapper_display_v1_DisplayAddOrReplace_config_led_backpack_tag) { - WS_DEBUG_PRINTLN("[display] LED Backpack support coming soon!"); - delete display; - return false; - } else if (msgAdd->which_config == - wippersnapper_display_v1_DisplayAddOrReplace_config_char_lcd_tag) { - WS_DEBUG_PRINTLN("[display] Character LCD support coming soon!"); - delete display; - return false; + &msgAdd->interface_type.spi_tft); } else { WS_DEBUG_PRINTLN("[display] Unsupported display configuration type!"); delete display; diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index 5cb7bc0d2..d74c2d733 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -63,17 +63,6 @@ class dispDrvBase { : _pin_cs(cs), _pin_dc(dc), _pin_mosi(mosi), _pin_sck(sck), _pin_rst(rst), _pin_miso(miso) {} - /*! - @brief Creates a new I2C output component driver. - @param i2c - The I2C hardware interface, default is Wire. - @param sensorAddress - The I2C sensor's unique address. - */ - dispDrvBase(TwoWire *i2c, uint16_t sensorAddress) { - // No-op constructor - } - /*! @brief Destructor for the base display driver. This destructor is virtual to allow derived classes to clean up @@ -124,7 +113,7 @@ class dispDrvBase { @param r The rotation of the display (0-3). */ - virtual void setRotation(uint8_t r) { _rotation = r; } + void setRotation(uint8_t r) { _rotation = r; } /*! @brief Sets the text size for the display. @@ -135,42 +124,19 @@ class dispDrvBase { */ virtual void setTextSize(uint8_t s) { _text_sz = s; } - /*! - @brief Sets the brightness for the display (if supported). - @param brightness - The brightness level to set. - @note This method can be overridden by derived classes to provide - specific functionality. - */ - virtual void setBrightness(int32_t brightness) { _brightness = brightness; } - - /*! - @brief Sets the alignment for the display (if supported). - @param alignment - The alignment to set. - @note This method can be overridden by derived classes to provide - specific functionality. - */ - virtual void setAlignment(uint32_t alignment) { _alignment = alignment; } - protected: - int16_t _pin_dc; ///< Data/Command pin - int16_t _pin_rst; ///< Reset pin - int16_t _pin_cs; ///< Chip Select pin - int16_t _pin_busy; ///< Optional Busy pin - int16_t _pin_sram_cs; ///< Optional EPD SRAM chip select pin - uint16_t _pin_mosi; ///< Optional MOSI pin for SPI TFT displays - uint16_t _pin_miso; ///< Optional MISO pin for SPI TFT displays - uint16_t _pin_sck; ///< Optional SCK pin for SPI TFT displays - TwoWire *_i2c; ///< Optional pointer to the I2C driver's Wire object - uint16_t _sensorAddress; ///< Optional I2C sensor address - uint8_t _text_sz = 1; ///< Optional Text size for displaying a message - int16_t _height; ///< Optional Height of the display - int16_t _width; ///< Optional Width of the display - uint8_t _rotation; ///< Optional Rotation of the display - int32_t _brightness; ///< Optional Brightness of the display (if supported) - uint32_t _alignment; ///< Optional Alignment of the display (specific to - ///< drivers like LED backpacks) + int16_t _pin_dc; ///< Data/Command pin + int16_t _pin_rst; ///< Reset pin + int16_t _pin_cs; ///< Chip Select pin + int16_t _pin_busy; ///< Optional Busy pin + int16_t _pin_sram_cs; ///< Optional EPD SRAM chip select pin + uint16_t _pin_mosi; ///< Optional MOSI pin for SPI TFT displays + uint16_t _pin_miso; ///< Optional MISO pin for SPI TFT displays + uint16_t _pin_sck; ///< Optional SCK pin for SPI TFT displays + uint8_t _text_sz = 1; ///< Text size for displaying a message + int16_t _height; ///< Height of the display + int16_t _width; ///< Width of the display + uint8_t _rotation; ///< Rotation of the display }; #endif // WS_DISP_DRV_BASE_H \ No newline at end of file diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index a564887ae..798932f99 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -173,8 +173,9 @@ int16_t DisplayHardware::parsePin(const char *pinStr) { Pointer to the SPI configuration structure for EPD. @return True if configuration was successful, False otherwise. */ -bool DisplayHardware::beginEPD(wippersnapper_display_v1_EPDConfig *config, - wippersnapper_display_v1_SpiConfig *spi_config) { +bool DisplayHardware::beginEPD( + wippersnapper_display_v1_EPDConfig *config, + wippersnapper_display_v1_EpdSpiConfig *spi_config) { // Validate pointers if (config == nullptr || spi_config == nullptr) { WS_DEBUG_PRINTLN("[display] EPD config or SPI config is null!"); @@ -272,8 +273,9 @@ void DisplayHardware::removeSuffix(const char *suffix) { Pointer to the SPI configuration structure for TFT. @return True if configuration was successful, False otherwise. */ -bool DisplayHardware::beginTft(wippersnapper_display_v1_TftConfig *config, - wippersnapper_display_v1_SpiConfig *spi_config) { +bool DisplayHardware::beginTft( + wippersnapper_display_v1_TftConfig *config, + wippersnapper_display_v1_TftSpiConfig *spi_config) { // Validate pointers if (config == nullptr || spi_config == nullptr) { WS_DEBUG_PRINTLN("[display] EPD config or SPI config is null!"); @@ -331,133 +333,6 @@ bool DisplayHardware::beginTft(wippersnapper_display_v1_TftConfig *config, return true; } -/*! - @brief Attempts to configure and initialize an OLED display - @param config - Pointer to the OLED's configuration structure. - @param i2c_config - Pointer to the I2C configuration structure. - @return True if configuration was successful, False otherwise. -*/ -bool DisplayHardware::beginOled( - wippersnapper_display_v1_OledConfig *config, - wippersnapper_display_v1_I2cConfig *i2c_config) { - // Validate pointers - if (config == nullptr || i2c_config == nullptr || !i2c_config->has_i2c) - return false; - - // If we already have a display driver assigned to this hardware instance, - // clean it up! - if (_drvDisp) { - delete _drvDisp; - _drvDisp = nullptr; - } - - // Initialize OLED display driver based on device name - if (strnlen(i2c_config->i2c.i2c_device_name, - sizeof(i2c_config->i2c.i2c_device_name)) < - sizeof(i2c_config->i2c.i2c_device_name) && - strcmp(i2c_config->i2c.i2c_device_name, "SSD1306") == 0) { - _drvDisp = new dispDrvSsd1306(WS._i2cPort0->getBus(), - i2c_config->i2c.i2c_device_address); - } else if (strnlen(i2c_config->i2c.i2c_device_name, - sizeof(i2c_config->i2c.i2c_device_name)) < - sizeof(i2c_config->i2c.i2c_device_name) && - strcmp(i2c_config->i2c.i2c_device_name, "SH1107") == 0) { - _drvDisp = new dispDrvSh1107(WS._i2cPort0->getBus(), - i2c_config->i2c.i2c_device_address); - } else { - WS_DEBUG_PRINTLN("[display] Unsupported OLED driver!"); - return false; - } - - // Validate that the display driver was created successfully - if (!_drvDisp) { - WS_DEBUG_PRINTLN("[display] Failed to create display driver!"); - _drvDisp = nullptr; - return false; - } - - // Configure display dimensions and text size - _drvDisp->setWidth(config->width); - _drvDisp->setHeight(config->height); - _drvDisp->setTextSize(config->text_size); - - // Initialize the display driver - if (!_drvDisp->begin()) { - WS_DEBUG_PRINTLN("[display] Failed to begin display driver!"); - delete _drvDisp; - _drvDisp = nullptr; - return false; - } - - WS_DEBUG_PRINTLN("[display] OLED initialized successfully."); - return true; -} - -/*! - @brief Attempts to configure and initialize an LED Backpack display - @param config - Pointer to the LED Backpack's configuration structure. - @param i2c_config - Pointer to the I2C configuration structure. - @return True if configuration was successful, False otherwise. -*/ -bool DisplayHardware::beginLedBackpack( - wippersnapper_display_v1_LEDBackpackConfig *config, - wippersnapper_display_v1_I2cConfig *i2c_config) { - // Validate pointers - if (config == nullptr || i2c_config == nullptr || !i2c_config->has_i2c) - return false; - - // If we already have a display driver assigned to this hardware instance, - // clean it up! - if (_drvDisp) { - delete _drvDisp; - _drvDisp = nullptr; - } - - // Initialize OLED display driver based on device name - if (strnlen(i2c_config->i2c.i2c_device_name, - sizeof(i2c_config->i2c.i2c_device_name)) < - sizeof(i2c_config->i2c.i2c_device_name) && - strcmp(i2c_config->i2c.i2c_device_name, "7seg") == 0) { - _drvDisp = new dispDrv7Seg(WS._i2cPort0->getBus(), - i2c_config->i2c.i2c_device_address); - } else if (strnlen(i2c_config->i2c.i2c_device_name, - sizeof(i2c_config->i2c.i2c_device_name)) < - sizeof(i2c_config->i2c.i2c_device_name) && - strcmp(i2c_config->i2c.i2c_device_name, "quadalphanum") == 0) { - _drvDisp = new dispDrvQuadAlphaNum(WS._i2cPort0->getBus(), - i2c_config->i2c.i2c_device_address); - } else { - WS_DEBUG_PRINTLN("[display] Unsupported OLED driver!"); - return false; - } - - // Validate that the display driver was created successfully - if (!_drvDisp) { - WS_DEBUG_PRINTLN("[display] Failed to create display driver!"); - _drvDisp = nullptr; - return false; - } - - // Configure display dimensions and text size - _drvDisp->setAlignment(config->alignment); - _drvDisp->setBrightness(config->brightness); - - // Initialize the display driver - if (!_drvDisp->begin()) { - WS_DEBUG_PRINTLN("[display] Failed to begin driver!"); - delete _drvDisp; - _drvDisp = nullptr; - return false; - } - - WS_DEBUG_PRINTLN("[display] LED backpack initialized successfully."); - return true; -} - /*! @brief Gets the name of the display hardware instance. @return The name of the display hardware instance. diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 64289f825..9446f1467 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -15,11 +15,7 @@ #ifndef WS_DISPLAY_HARDWARE_H #define WS_DISPLAY_HARDWARE_H #include "Wippersnapper.h" -#include "drivers/dispDrv7Seg.h" #include "drivers/dispDrvBase.h" -#include "drivers/dispDrvQuadAlphaNum.h" -#include "drivers/dispDrvSh1107.h" -#include "drivers/dispDrvSsd1306.h" #include "drivers/dispDrvSt7789.h" #include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h" #include "drivers/dispDrvThinkInkGrayscale4T5.h" @@ -44,13 +40,9 @@ class DisplayHardware { void setType(wippersnapper_display_v1_DisplayType type); wippersnapper_display_v1_DisplayType getType(); bool beginEPD(wippersnapper_display_v1_EPDConfig *config, - wippersnapper_display_v1_SpiConfig *spi_config); + wippersnapper_display_v1_EpdSpiConfig *spi_config); bool beginTft(wippersnapper_display_v1_TftConfig *config, - wippersnapper_display_v1_SpiConfig *spi_config); - bool beginOled(wippersnapper_display_v1_OledConfig *config, - wippersnapper_display_v1_I2cConfig *i2c_config); - bool beginLedBackpack(wippersnapper_display_v1_LEDBackpackConfig *config, - wippersnapper_display_v1_I2cConfig *i2c_config); + wippersnapper_display_v1_TftSpiConfig *spi_config); // // API for Adafruit_GFX that abstracts hardware functionality diff --git a/src/components/i2c/WipperSnapper_I2C.cpp b/src/components/i2c/WipperSnapper_I2C.cpp index f59240833..2947702c2 100644 --- a/src/components/i2c/WipperSnapper_I2C.cpp +++ b/src/components/i2c/WipperSnapper_I2C.cpp @@ -932,6 +932,105 @@ bool WipperSnapper_Component_I2C::initI2CDevice( _adt7410->configureDriver(msgDeviceInitReq); drivers.push_back(_adt7410); WS_DEBUG_PRINTLN("ADT7410 Initialized Successfully!"); + } else if (strcmp("quadalphanum", msgDeviceInitReq->i2c_device_name) == 0) { + _quadAlphaNum = + new WipperSnapper_I2C_Driver_Out_QuadAlphaNum(this->_i2c, i2cAddress); + _quadAlphaNum->ConfigureI2CBackpack( + msgDeviceInitReq->i2c_output_add.config.led_backpack_config.brightness, + msgDeviceInitReq->i2c_output_add.config.led_backpack_config.alignment); + if (!_quadAlphaNum->begin()) { + WS_DEBUG_PRINTLN("ERROR: Failed to initialize Quad Alphanum. Display!"); + _busStatusResponse = + wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL; + return false; + } + _drivers_out.push_back(_quadAlphaNum); + WS_DEBUG_PRINTLN("Quad Alphanum. Display Initialized Successfully!"); + } else if (strcmp("chardisplay16x2", msgDeviceInitReq->i2c_device_name) == + 0 || + strcmp("chardisplay20x4", msgDeviceInitReq->i2c_device_name) == + 0) { + _charLcd = new WipperSnapper_I2C_Driver_Out_CharLcd(this->_i2c, i2cAddress); + _charLcd->ConfigureCharLcd( + msgDeviceInitReq->i2c_output_add.config.char_lcd_config.rows, + msgDeviceInitReq->i2c_output_add.config.char_lcd_config.columns); + if (!_charLcd->begin()) { + WS_DEBUG_PRINTLN("ERROR: Failed to initialize Character LCD!"); + _busStatusResponse = + wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL; + return false; + } + _drivers_out.push_back(_charLcd); + WS_DEBUG_PRINTLN("Char LCD Display Initialized Successfully!"); + } else if (strcmp("7seg", msgDeviceInitReq->i2c_device_name) == 0) { + _sevenSeg = new WipperSnapper_I2C_Driver_Out_7Seg(this->_i2c, i2cAddress); + _sevenSeg->ConfigureI2CBackpack( + msgDeviceInitReq->i2c_output_add.config.led_backpack_config.brightness, + msgDeviceInitReq->i2c_output_add.config.led_backpack_config.alignment); + if (!_sevenSeg->begin()) { + WS_DEBUG_PRINTLN("ERROR: Failed to initialize 7-Segement LED Matrix!"); + _busStatusResponse = + wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL; + return false; + } + _drivers_out.push_back(_sevenSeg); + WS_DEBUG_PRINTLN("7-Segement LED Matrix Initialized Successfully!"); + } else if (strcmp("fthrwingoled128x64", msgDeviceInitReq->i2c_device_name) == + 0 || + strcmp("fthrwingoled128x64lg", + msgDeviceInitReq->i2c_device_name) == 0) { + WS_DEBUG_PRINTLN("SH1107 display detected!"); + _sh1107 = new WipperSnapper_I2C_Driver_Out_SH1107(this->_i2c, i2cAddress); + WS_DEBUG_PRINTLN("Configuring SH1107 display..."); + _sh1107->ConfigureSH1107( + (uint8_t)msgDeviceInitReq->i2c_output_add.config.ssd1306_config.width, + (uint8_t)msgDeviceInitReq->i2c_output_add.config.ssd1306_config.height, + (uint8_t) + msgDeviceInitReq->i2c_output_add.config.ssd1306_config.text_size, + OLED_128X64_WING_ROTATION_90); // fixed as currently the only screen is + // 128x64wing (needs a rotation of 1 / 90degrees and constructor w/h swap). + if (!_sh1107->begin()) { + WS_DEBUG_PRINTLN("ERROR: Failed to initialize sh1107!"); + _busStatusResponse = + wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL; + return false; + } + WS_DEBUG_PRINTLN("SH1107 display configured successfully!"); + _drivers_out.push_back(_sh1107); + WS_DEBUG_PRINTLN("SH1107 display initialized Successfully!"); + } else if (strcmp("oled32x64large", msgDeviceInitReq->i2c_device_name) == 0 || + strcmp("oled64x32default", msgDeviceInitReq->i2c_device_name) == + 0 || + strcmp("oled64x32large", msgDeviceInitReq->i2c_device_name) == 0 || + strcmp("fthrwingoled128x32", msgDeviceInitReq->i2c_device_name) == + 0 || + strcmp("fthrwingoled128x32lg", + msgDeviceInitReq->i2c_device_name) == 0 || + strcmp("oled128x32default", msgDeviceInitReq->i2c_device_name) == + 0 || + strcmp("oled128x32large", msgDeviceInitReq->i2c_device_name) == + 0 || + strcmp("oled128x64default", msgDeviceInitReq->i2c_device_name) == + 0 || + strcmp("oled128x64large", msgDeviceInitReq->i2c_device_name) == + 0) { + WS_DEBUG_PRINTLN("SSD1306 display detected!"); + _ssd1306 = new WipperSnapper_I2C_Driver_Out_Ssd1306(this->_i2c, i2cAddress); + WS_DEBUG_PRINTLN("Configuring SSD1306 display..."); + _ssd1306->ConfigureSSD1306( + (uint8_t)msgDeviceInitReq->i2c_output_add.config.ssd1306_config.width, + (uint8_t)msgDeviceInitReq->i2c_output_add.config.ssd1306_config.height, + (uint8_t) + msgDeviceInitReq->i2c_output_add.config.ssd1306_config.text_size); + if (!_ssd1306->begin()) { + WS_DEBUG_PRINTLN("ERROR: Failed to initialize ssd1306!"); + _busStatusResponse = + wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_DEVICE_INIT_FAIL; + return false; + } + WS_DEBUG_PRINTLN("SSD1306 display configured successfully!"); + _drivers_out.push_back(_ssd1306); + WS_DEBUG_PRINTLN("SSD1306 display initialized Successfully!"); } else { WS_DEBUG_PRINTLN("ERROR: I2C device type not found!") _busStatusResponse = @@ -1001,6 +1100,27 @@ void WipperSnapper_Component_I2C::deinitI2CDevice( } } + // Check for output drivers + std::vector::iterator out_iter, out_end; + for (out_iter = _drivers_out.begin(), out_end = _drivers_out.end(); + out_iter != out_end; ++out_iter) { + if ((*out_iter)->getI2CAddress() == deviceAddr) { + // Set the driver to nullptr + *out_iter = nullptr; +// ESP-IDF, Erase–remove iter ptr from driver vector +#if defined(ARDUINO_ARCH_ESP32) || defined(ARDUINO_ARCH_ESP8266) + *out_iter = nullptr; + _drivers_out.erase( + remove(_drivers_out.begin(), _drivers_out.end(), nullptr), + _drivers_out.end()); +#else + // Arduino can not erase-remove, erase only + _drivers_out.erase(out_iter); +#endif + WS_DEBUG_PRINTLN("I2C Device De-initialized!"); + } + } + _busStatusResponse = wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_SUCCESS; } @@ -1070,6 +1190,147 @@ void WipperSnapper_Component_I2C::fillEventMessage( msgi2cResponse->payload.resp_i2c_device_event.sensor_event_count++; } +/*******************************************************************************/ +/*! + @brief Displays a sensor event message on the TFT + @param msgi2cResponse + A pointer to an I2CResponse message. + @param sensorAddress + The unique I2C address of the sensor. +*/ +/*******************************************************************************/ +void WipperSnapper_Component_I2C::displayDeviceEventMessage( + wippersnapper_signal_v1_I2CResponse *msgi2cResponse, + uint32_t sensorAddress) { + + pb_size_t numEvents = + msgi2cResponse->payload.resp_i2c_device_event.sensor_event_count; + + char buffer[100]; + for (int i = 0; i < numEvents; i++) { + float value = + msgi2cResponse->payload.resp_i2c_device_event.sensor_event[i].value; + + switch ( + msgi2cResponse->payload.resp_i2c_device_event.sensor_event[i].type) { + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE: + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE: + snprintf(buffer, 100, "[I2C: %#x] Read: %0.3f *C\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_AMBIENT_TEMPERATURE_FAHRENHEIT: + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_OBJECT_TEMPERATURE_FAHRENHEIT: + snprintf(buffer, 100, "[I2C: %#x] Read: %0.3f *F\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_RELATIVE_HUMIDITY: + snprintf(buffer, 100, "[I2C: %#x] Read: %0.3f %% rh\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_PRESSURE: + snprintf(buffer, 100, "[I2C: %#x] Read: %0.3f hPA\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_ALTITUDE: + snprintf(buffer, 100, "[I2C: %x] Read: %0.3f m\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_LIGHT: + snprintf(buffer, 100, "[I2C: %x] Read: %0.3f lux\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_PM10_STD: + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_PM25_STD: + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_PM100_STD: + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_CO2: + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_ECO2: + snprintf(buffer, 100, "[I2C: %x] Read: %0.3f ppm\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_TVOC: + snprintf(buffer, 100, "[I2C: %x] Read: %0.3f ppb\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_UNITLESS_PERCENT: + snprintf(buffer, 100, "[I2C: %x] Read: %0.3f%%\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_VOLTAGE: + snprintf(buffer, 100, "[I2C: %x] Read: %0.3f V\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_CURRENT: + snprintf(buffer, 100, "[I2C: %x] Read: %0.3f mA\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_RAW: + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_PROXIMITY: + snprintf(buffer, 100, "[I2C: %x] Read: %0.3f\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_GAS_RESISTANCE: + snprintf(buffer, 100, "[I2C: %x] Read: %0.3f Ohms\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_NOX_INDEX: + snprintf(buffer, 100, "[I2C: %x] Read: %0.3f NOX\n", + (unsigned int)sensorAddress, value); + break; + case wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_VOC_INDEX: + snprintf(buffer, 100, "[I2C: %x] Read: %0.3f VOC\n", + (unsigned int)sensorAddress, value); + break; + default: + break; + } + } +} + +/*******************************************************************************/ +/*! + @brief Handles an I2CDeviceOutputWrite message. + @param msgDeviceWrite + A decoded I2CDeviceOutputWrite message. + @returns True if the message was handled successfully, false otherwise. +*/ +/*******************************************************************************/ +bool WipperSnapper_Component_I2C::Handle_I2cDeviceOutputWrite( + wippersnapper_i2c_v1_I2CDeviceOutputWrite *msgDeviceWrite) { + + // Create a ptr to the base driver out + WipperSnapper_I2C_Driver_Out *driver_out = nullptr; + // Find the matching driver by address in the _drivers_out vector + for (size_t i = 0; i < _drivers_out.size(); i++) { + if (_drivers_out[i]->getI2CAddress() == + msgDeviceWrite->i2c_device_address) { + driver_out = _drivers_out[i]; + break; + } + } + if (driver_out == nullptr) { + WS_DEBUG_PRINTLN("ERROR: I2c output driver not found within drivers_out!"); + return false; + } + + // Call the output_msg + if (msgDeviceWrite->which_output_msg == + wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_led_backpack_tag) { + driver_out->WriteLedBackpack( + &msgDeviceWrite->output_msg.write_led_backpack); + } else if (msgDeviceWrite->which_output_msg == + wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_char_lcd_tag) { + driver_out->WriteMessageCharLCD(&msgDeviceWrite->output_msg.write_char_lcd); + } else if (msgDeviceWrite->which_output_msg == + wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_ssd1306_tag) { + driver_out->WriteMessageSSD1306( + msgDeviceWrite->output_msg.write_ssd1306.message); + } else { + WS_DEBUG_PRINTLN("ERROR: Unknown i2c output message type!"); + return false; + } + return true; +} + /*******************************************************************************/ /*! @brief Queries all I2C device drivers for new values. Fills and sends an @@ -1331,6 +1592,8 @@ void WipperSnapper_Component_I2C::update() { continue; } + displayDeviceEventMessage(&msgi2cResponse, (*iter)->getI2CAddress()); + // Encode and publish I2CDeviceEvent message if (!encodePublishI2CDeviceEventMsg(&msgi2cResponse, (*iter)->getI2CAddress())) { diff --git a/src/components/i2c/WipperSnapper_I2C.h b/src/components/i2c/WipperSnapper_I2C.h index b858c8ff3..a83765370 100644 --- a/src/components/i2c/WipperSnapper_I2C.h +++ b/src/components/i2c/WipperSnapper_I2C.h @@ -57,6 +57,12 @@ #include "drivers/WipperSnapper_I2C_Driver_MPRLS.h" #include "drivers/WipperSnapper_I2C_Driver_MS8607.h" #include "drivers/WipperSnapper_I2C_Driver_NAU7802.h" +#include "drivers/WipperSnapper_I2C_Driver_Out.h" +#include "drivers/WipperSnapper_I2C_Driver_Out_7Seg.h" +#include "drivers/WipperSnapper_I2C_Driver_Out_CharLcd.h" +#include "drivers/WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h" +#include "drivers/WipperSnapper_I2C_Driver_Out_Sh1107.h" +#include "drivers/WipperSnapper_I2C_Driver_Out_Ssd1306.h" #include "drivers/WipperSnapper_I2C_Driver_PCT2075.h" #include "drivers/WipperSnapper_I2C_Driver_PM25.h" #include "drivers/WipperSnapper_I2C_Driver_SCD30.h" @@ -107,7 +113,6 @@ class WipperSnapper_Component_I2C { wippersnapper_i2c_v1_I2CBusScanResponse scanAddresses(); bool initI2CDevice(wippersnapper_i2c_v1_I2CDeviceInitRequest *msgDeviceInitReq); - TwoWire *getBus() { return _i2c; } void updateI2CDeviceProperties( wippersnapper_i2c_v1_I2CDeviceUpdateRequest *msgDeviceUpdateReq); @@ -116,6 +121,9 @@ class WipperSnapper_Component_I2C { void update(); + bool Handle_I2cDeviceOutputWrite( + wippersnapper_i2c_v1_I2CDeviceOutputWrite *msgDeviceWrite); + void sensorEventRead( std::vector::iterator &iter, unsigned long curTime, @@ -133,6 +141,10 @@ class WipperSnapper_Component_I2C { float value, wippersnapper_i2c_v1_SensorType sensorType); + void + displayDeviceEventMessage(wippersnapper_signal_v1_I2CResponse *msgi2cResponse, + uint32_t sensorAddress); + bool encodePublishI2CDeviceEventMsg( wippersnapper_signal_v1_I2CResponse *msgi2cResponse, uint32_t sensorAddress); @@ -144,6 +156,8 @@ class WipperSnapper_Component_I2C { wippersnapper_i2c_v1_BusResponse _busStatusResponse; std::vector drivers; ///< List of i2c sensor drivers + std::vector + _drivers_out; ///< List of i2c output drivers // Sensor driver objects WipperSnapper_I2C_Driver_AHTX0 *_ahtx0 = nullptr; WipperSnapper_I2C_Driver_AS5600 *_as5600 = nullptr; @@ -207,6 +221,11 @@ class WipperSnapper_Component_I2C { WipperSnapper_I2C_Driver_VL6180X *_vl6180x = nullptr; WipperSnapper_I2C_Driver_MAX17048 *_max17048 = nullptr; WipperSnapper_I2C_Driver_ADT7410 *_adt7410 = nullptr; + WipperSnapper_I2C_Driver_Out_QuadAlphaNum *_quadAlphaNum = nullptr; + WipperSnapper_I2C_Driver_Out_CharLcd *_charLcd = nullptr; + WipperSnapper_I2C_Driver_Out_7Seg *_sevenSeg = nullptr; + WipperSnapper_I2C_Driver_Out_SH1107 *_sh1107 = nullptr; + WipperSnapper_I2C_Driver_Out_Ssd1306 *_ssd1306 = nullptr; }; extern Wippersnapper WS; diff --git a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out.h new file mode 100644 index 000000000..c92debec7 --- /dev/null +++ b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out.h @@ -0,0 +1,145 @@ +/*! + * @file WipperSnapper_I2C_Driver_Out.h + * + * Derived class for I2C output driver components + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_H +#define WIPPERSNAPPER_I2C_DRIVER_OUT_H + +#include "WipperSnapper_I2C_Driver.h" +#include + +/*! + @brief Derived class for I2C output component drivers. +*/ +class WipperSnapper_I2C_Driver_Out : public WipperSnapper_I2C_Driver { + +public: + /*! + @brief Creates a new I2C output component driver. + @param i2c + The I2C hardware interface, default is Wire. + @param sensorAddress + The I2C sensor's unique address. + */ + WipperSnapper_I2C_Driver_Out(TwoWire *i2c, uint16_t sensorAddress) + : WipperSnapper_I2C_Driver(i2c, sensorAddress) { + // No-op constructor + } + + /*! + @brief Destructor for an I2C output component. + */ + virtual ~WipperSnapper_I2C_Driver_Out() { + // No-op destructor + } + + /*! + @brief Writes a message to an i2c output device. + @param message + The message to be displayed. +*/ + virtual void WriteMessage(const char *message) { + // noop + } + + /*! + @brief Configures a SSD1306 OLED display. Must be called before driver + begin() + @param width + The width of the display in pixels. + @param height + The height of the display in pixels. + @param text_size + The display's text size. + @param rotation + The rotation of the display in degrees, default is 0. + */ + virtual void ConfigureSSD1306(uint8_t width, uint8_t height, + uint8_t text_size, uint8_t rotation = 0) { + // noop + } + + /*! + @brief Writes a message to the SSD1306 display. + @param message + The message to be displayed. + */ + virtual void WriteMessageSSD1306(const char *message) { + // noop + } + + /*! + @brief Configures a LED backpack. + @param brightness + The brightness of the LED backpack. + @param alignment + The alignment of the LED backpack. + */ + virtual void ConfigureI2CBackpack(int32_t brightness, uint32_t alignment) { + // noop + } + + /*! + @brief Sets the brightness of the LED backpack. + @param b + The brightness value, from 0 (off) to 15 (full brightness). + */ + virtual void SetLedBackpackBrightness(uint8_t b) { + // noop + } + + /*! + @brief Writes a message to the LED backpack. + @param msg_write + Pointer to a wippersnapper_i2c_v1_LedBackpackWrite message. + */ + void WriteLedBackpack(wippersnapper_i2c_v1_LEDBackpackWrite *msg_write) { + WriteMessage(msg_write->message); + } + + /*! + @brief Configures a character LCD. + @param rows + The number of rows in the LCD. + @param cols + The number of columns in the LCD. + */ + virtual void ConfigureCharLcd(uint32_t rows, uint32_t cols) { + // noop + } + + /*! + @brief Turns the character LCD backlight on or off. + @param enable + True to enable the backlight, false to disable it. + */ + void EnableCharLcdBacklight(bool enable) { + // noop + } + + /*! + @brief Writes a message to the LCD. + @param write_char_lcd + Points to a CharLCDWrite message. + @param enable_backlight + True if the backlight should be enabled, false otherwise. + */ + void WriteMessageCharLCD(wippersnapper_i2c_v1_CharLCDWrite *write_char_lcd, + bool enable_backlight = true) { + EnableCharLcdBacklight(enable_backlight); + WriteMessage(write_char_lcd->message); + } +}; + +#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_H diff --git a/src/components/display/drivers/dispDrv7Seg.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_7Seg.h similarity index 55% rename from src/components/display/drivers/dispDrv7Seg.h rename to src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_7Seg.h index d06d9d6ff..1184e844a 100644 --- a/src/components/display/drivers/dispDrv7Seg.h +++ b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_7Seg.h @@ -1,22 +1,29 @@ /*! - * @file src/components/display/drivers/dispDrv7Seg.h + * @file WipperSnapper_I2C_Driver_Out_7Seg.h * - * Driver for 7-Segment LED Backpack displays. + * Device driver designed specifically to work with the Adafruit LED 7-Segment + * I2C backpacks: + * ----> http://www.adafruit.com/products/881 + * ----> http://www.adafruit.com/products/880 + * ----> http://www.adafruit.com/products/879 + * ----> http://www.adafruit.com/products/878 * * Adafruit invests time and resources providing this open source code, * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * - * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * Copyright (c) Brent Rubell for Adafruit Industries 2025 * - * BSD license, all text here must be included in any redistribution. + * MIT license, all text here must be included in any redistribution. * */ -#ifndef WS_DISP_DRV_7Seg -#define WS_DISP_DRV_7Seg -#include "dispDrvBase.h" +#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_7SEG_H +#define WIPPERSNAPPER_I2C_DRIVER_OUT_7SEG_H + +#include "WipperSnapper_I2C_Driver_Out.h" #include +#include #define LED_BACKPACK_ALIGNMENT_UNSPECIFIED 0 ///< Unspecified alignment #define LED_BACKPACK_ALIGNMENT_LEFT 1 ///< Left alignment @@ -29,48 +36,79 @@ 0b01100011 ///< Degree symbol for 7-segment display /*! - @brief Driver for 7-segment LED backpack displays. + @brief Class that provides a driver interface for 7-Segment + Displays w/I2C Backpack */ -class dispDrv7Seg : public dispDrvBase { +class WipperSnapper_I2C_Driver_Out_7Seg : public WipperSnapper_I2C_Driver_Out { + public: + /*******************************************************************************/ /*! - @brief Constructor for the 7-segment LED matrix. + @brief Constructor for a 7-Segment display driver. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. */ - dispDrv7Seg(TwoWire *i2c, uint16_t sensorAddress) - : dispDrvBase(i2c, sensorAddress), _matrix(nullptr) { - _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; + /*******************************************************************************/ + WipperSnapper_I2C_Driver_Out_7Seg(TwoWire *i2c, uint16_t sensorAddress) + : WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) { + _i2c = i2c; + _sensorAddress = sensorAddress; } /*! - @brief Destructor for the 7-segment LED backpack driver. + @brief Destructor for a 7-Segment display driver. */ - ~dispDrv7Seg() { - if (_matrix) { + ~WipperSnapper_I2C_Driver_Out_7Seg() { + if (_matrix != nullptr) { delete _matrix; _matrix = nullptr; } } /*! - @brief Attempts to initialize the 7-segment LED backpack driver. - @return True if the matrix was initialized successfully, false otherwise. + @brief Initializes the 7-segment LED matrix and begins I2C + communication. + @returns True if initialized successfully, False otherwise. */ - bool begin() override { + bool begin() { _matrix = new Adafruit_7segment(); - return _matrix->begin(_sensorAddress, _i2c); + bool did_begin = _matrix->begin(_sensorAddress, _i2c); + return did_begin; } /*! - @brief Sets the text alignment for the matrix. - @param alignment - The desired alignment to set (LEFT or RIGHT). - */ - void setAlignment(uint32_t alignment) override { + @brief Configures the LED matrix's I2C backpack. + @param brightness + The brightness of the i2c backpack (0-15). + @param alignment + The alignment of the i2c backpack's LED matrix (left/right). +*/ + void ConfigureI2CBackpack(int32_t brightness, uint32_t alignment) { if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) { _alignment = LED_BACKPACK_ALIGNMENT_RIGHT; } else { _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; } + + // Note: Adafruit_LEDBackpack normalizes only > 15, but not < 0, + // so, here we're normalizing < 0 to 8 (median brightness) + if (brightness < 0) { + brightness = 8; // Set to median brightness if out of range + } + } + + /*! + @brief Sets the brightness of the LED backpack. + @param b + The brightness value, from 0 (off) to 15 (full brightness). + */ + void SetLedBackpackBrightness(uint8_t b) { + if (_matrix == nullptr) { + return; + } + _matrix->setBrightness(b); } /*! @@ -79,7 +117,7 @@ class dispDrv7Seg : public dispDrvBase { @param message The message to be displayed. */ - void writeMessage(const char *message) override { + void WriteMessage(const char *message) { if (_matrix == nullptr || message == nullptr) { return; } @@ -158,8 +196,14 @@ class dispDrv7Seg : public dispDrvBase { _matrix->writeDisplay(); } -private: - Adafruit_7segment *_matrix; +protected: + Adafruit_7segment *_matrix = + nullptr; ///< ptr to a 7-segment LED matrix object + int32_t _brightness; ///< Brightness of the LED backpack, from 0 (off) to 15 + ///< (full brightness) + uint32_t _alignment = + LED_BACKPACK_ALIGNMENT_DEFAULT; ///< Determines L/R alignment of the + ///< message displayed }; -#endif // WS_DISP_DRV_7Seg \ No newline at end of file +#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_7SEG_H \ No newline at end of file diff --git a/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_CharLcd.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_CharLcd.h new file mode 100644 index 000000000..e00572c81 --- /dev/null +++ b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_CharLcd.h @@ -0,0 +1,163 @@ +/*! + * @file WipperSnapper_I2C_Driver_Out_CharLcd.h + * + * Device driver for I2C Character LCDs (HD44780) + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell for Adafruit Industries 2025 + * + * MIT license, all text here must be included in any redistribution. + * + */ + +#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_CHARLCD_H +#define WIPPERSNAPPER_I2C_DRIVER_OUT_CHARLCD_H + +#include "WipperSnapper_I2C_Driver_Out.h" +#include + +/*! + @brief Class that provides a driver interface for a lcd character display. + This class is a wrapper around the Adafruit_LiquidCrystal library. +*/ +class WipperSnapper_I2C_Driver_Out_CharLcd + : public WipperSnapper_I2C_Driver_Out { + +public: + /*! + @brief Constructor for a LCD character display. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. + */ + WipperSnapper_I2C_Driver_Out_CharLcd(TwoWire *i2c, uint16_t sensorAddress) + : WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) { + _i2c = i2c; + _sensorAddress = sensorAddress; + } + + /*! + @brief Destructor for an MS8607 sensor. + */ + ~WipperSnapper_I2C_Driver_Out_CharLcd() { + if (_lcd != nullptr) { + delete _lcd; + _lcd = nullptr; + } + } + + /*! + @brief Initializes the drvOutQuadAlphaNum component and begins I2C. + @returns True if initialized successfully, False otherwise. + */ + bool begin() { + _lcd = new Adafruit_LiquidCrystal(_sensorAddress, _i2c); + bool did_begin = _lcd->begin(_cols, _rows); + if (did_begin) { + _lcd->setBacklight(HIGH); + } + return did_begin; + } + + /*! + @brief Writes a message to the LCD. + @note MUST be called prior to begin() to configure the LCD's size + @param rows + The number of rows in the LCD. + @param cols + The number of columns in the LCD. + */ + void ConfigureCharLcd(uint8_t rows, uint8_t cols) { + _rows = rows; + _cols = cols; + } + + /*! + @brief Turns the character LCD backlight on or off. + @param enable + True to enable the backlight, false to disable it. + */ + void EnableCharLcdBacklight(bool enable = true) { + if (_lcd == nullptr) + return; + + if (enable) { + _lcd->setBacklight(HIGH); + } else { + _lcd->setBacklight(LOW); + } + } + + /*! + @brief Writes a message to the LCD. + @param message + The message to be displayed. + */ + void WriteMessage(const char *message) { + if (_lcd == nullptr) + return; + + // Before writing, let's clear the display + _lcd->clear(); + + size_t message_length = strlen(message); + size_t cur_idx = 0; // Current index in the message + + // Write each row until it hits: \n, or the end of the message, or the last + // column/row position + for (int cur_row = 0; cur_row < _rows && cur_idx < message_length; + cur_row++) { + // Write each row out at the beginning of the row + _lcd->setCursor(0, cur_row); + for (int cur_col = 0; cur_col < _cols && cur_idx < message_length; + cur_col++) { + char c = message[cur_idx]; + if (c == '\\' && cur_idx + 1 < message_length && + (message[cur_idx + 1] == 'n' || message[cur_idx + 1] == 'r')) { + // Handle \r\n sequence as a single newline + if (message[cur_idx + 1] == 'r' && cur_idx + 3 < message_length && + message[cur_idx + 2] == '\\' && message[cur_idx + 3] == 'n') { + cur_idx += 4; // Skip \r\n and don't move the cursor two rows + break; // Move to the next row + } else { + if (message[cur_idx + 1] == 'r') { + _lcd->write('\\'); + _lcd->write('r'); + cur_idx += 2; // Skip the \r + } else { + cur_idx += 2; // Skip the \n + break; // Move to the next row + } + } + } else if ((c == 0x0A || c == 0x0D) && cur_idx + 1 < message_length) { + if (c == 0x0A && cur_idx + 1 < message_length && + message[cur_idx + 1] == 0x0D) { + cur_idx += 2; // Skip both LF and CR characters + } else { + cur_idx += 1; // Skip single newline character + } + break; // and move to the next row + } else if (c == 194 && cur_idx + 1 < message_length && + message[cur_idx + 1] == 176) { + cur_idx += 2; // Skip the degree symbol sequence in the buffer + _lcd->write(0xDF); // and write the degree symbol + } else { + _lcd->write(c); + cur_idx++; + } + } + } + } + +protected: + Adafruit_LiquidCrystal *_lcd = + nullptr; ///< Pointer to the Adafruit_LiquidCrystal object + uint8_t _rows; ///< Number of rows in the display + uint8_t _cols; ///< Number of columns in the display +}; + +#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_CHARLCD_H \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvQuadAlphaNum.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h similarity index 62% rename from src/components/display/drivers/dispDrvQuadAlphaNum.h rename to src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h index 7f603d818..02553e208 100644 --- a/src/components/display/drivers/dispDrvQuadAlphaNum.h +++ b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h @@ -1,22 +1,24 @@ /*! - * @file src/components/display/drivers/dispDrvQuadAlphaNum.h + * @file WipperSnapper_I2C_Driver_Out_QuadAlphaNum.h * - * Driver for Quad Alphanumeric 7-Segment LED Backpack displays. + * Device driver for Quad Alphanumeric Displays w/I2C Backpack * * Adafruit invests time and resources providing this open source code, * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * - * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * Copyright (c) Brent Rubell for Adafruit Industries 2025 * - * BSD license, all text here must be included in any redistribution. + * MIT license, all text here must be included in any redistribution. * */ -#ifndef WS_DISP_DRV_QUADALPHANUM -#define WS_DISP_DRV_QUADALPHANUM -#include "dispDrvBase.h" +#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_QUADALPHANUM_H +#define WIPPERSNAPPER_I2C_DRIVER_OUT_QUADALPHANUM_H + +#include "WipperSnapper_I2C_Driver_Out.h" #include +#include #define LED_BACKPACK_ALIGNMENT_UNSPECIFIED 0 ///< Unspecified alignment #define LED_BACKPACK_ALIGNMENT_LEFT 1 ///< Left alignment @@ -29,27 +31,34 @@ 0b0000000011100011 ///< Degree symbol for alphanumeric display /*! - @brief Driver for Quad Alphanumeric LED matrixes. + @brief Class that provides a driver interface for Quad Alphanumeric + Displays w/I2C Backpack */ -class dispDrvQuadAlphaNum : public dispDrvBase { +class WipperSnapper_I2C_Driver_Out_QuadAlphaNum + : public WipperSnapper_I2C_Driver_Out { + public: + /*******************************************************************************/ /*! - @brief Constructor for Quad Alphanumeric LED matrixes. - @param i2c - The I2C hardware interface, default is Wire. - @param sensorAddress - The I2C sensor's unique address. + @brief Constructor for an MS8607 sensor. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. */ - dispDrvQuadAlphaNum(TwoWire *i2c, uint16_t sensorAddress) - : dispDrvBase(i2c, sensorAddress), _alpha4(nullptr) { - _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; + /*******************************************************************************/ + WipperSnapper_I2C_Driver_Out_QuadAlphaNum(TwoWire *i2c, + uint16_t sensorAddress) + : WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) { + _i2c = i2c; + _sensorAddress = sensorAddress; } /*! - @brief Destructor for the 7-segment LED backpack driver. + @brief Destructor for an MS8607 sensor. */ - ~dispDrvQuadAlphaNum() { - if (_alpha4) { + ~WipperSnapper_I2C_Driver_Out_QuadAlphaNum() { + if (_alpha4 != nullptr) { delete _alpha4; _alpha4 = nullptr; } @@ -59,37 +68,39 @@ class dispDrvQuadAlphaNum : public dispDrvBase { @brief Initializes the drvOutQuadAlphaNum component and begins I2C. @returns True if initialized successfully, False otherwise. */ - bool begin() override { + bool begin() { _alpha4 = new Adafruit_AlphaNum4(); bool did_begin = _alpha4->begin(_sensorAddress, _i2c); _alpha4->setBrightness(_brightness); return did_begin; } + /*! + @brief Configures a LED backpack. + @param brightness + The brightness of the LED backpack. + @param alignment + The alignment of the LED backpack. +*/ + void ConfigureI2CBackpack(int32_t brightness, uint32_t alignment) { + if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) { + _alignment = LED_BACKPACK_ALIGNMENT_RIGHT; + } else { + _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; + } + _brightness = brightness; + } + /*! @brief Sets the brightness of the LED backpack. @param b The brightness value, from 0 (off) to 15 (full brightness). */ - void setBrightness(int32_t brightness) override { + void SetLedBackpackBrightness(uint8_t b) { if (_alpha4 == nullptr) { return; } - _alpha4->setBrightness(brightness); - } - - /*! - @brief Sets the alignment of the displayed text. - @param alignment - The alignment value, either LED_BACKPACK_ALIGNMENT_LEFT or - LED_BACKPACK_ALIGNMENT_RIGHT. - */ - void setAlignment(uint32_t alignment) override { - if (alignment == LED_BACKPACK_ALIGNMENT_RIGHT) { - _alignment = LED_BACKPACK_ALIGNMENT_RIGHT; - } else { - _alignment = LED_BACKPACK_ALIGNMENT_DEFAULT; - } + _alpha4->setBrightness(b); } /*! @@ -98,7 +109,7 @@ class dispDrvQuadAlphaNum : public dispDrvBase { @param message The message to be displayed. */ - void writeMessage(const char *message) override { + void WriteMessage(const char *message) { if (_alpha4 == nullptr || message == nullptr) { return; } @@ -154,8 +165,14 @@ class dispDrvQuadAlphaNum : public dispDrvBase { _alpha4->writeDisplay(); } -private: - Adafruit_AlphaNum4 *_alpha4; ///< Pointer to an Adafruit AlphaNum4 object +protected: + Adafruit_AlphaNum4 *_alpha4 = + nullptr; ///< ptr to a 4-digit alphanumeric display object + int32_t _brightness; ///< Brightness of the LED backpack, from 0 (off) to 15 + ///< (full brightness) + uint32_t _alignment = + LED_BACKPACK_ALIGNMENT_DEFAULT; ///< Determines L/R alignment of the + ///< message displayed }; -#endif // WS_DISP_DRV_QUADALPHANUM \ No newline at end of file +#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_QUADALPHANUM_H \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvSh1107.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Sh1107.h similarity index 50% rename from src/components/display/drivers/dispDrvSh1107.h rename to src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Sh1107.h index 42fbce33b..1ef27e450 100644 --- a/src/components/display/drivers/dispDrvSh1107.h +++ b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Sh1107.h @@ -1,5 +1,5 @@ /*! - * @file src/components/display/drivers/dispDrvSh1107.h + * @file WipperSnapper_I2C_Driver_Out_SH1107.h * * Device driver for a SH1107 OLED Display * @@ -12,11 +12,14 @@ * MIT license, all text here must be included in any redistribution. * */ -#ifndef WS_DISP_DRV_SH1107_H -#define WS_DISP_DRV_SH1107_H -#include "dispDrvBase.h" +#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_SH1107_H +#define WIPPERSNAPPER_I2C_DRIVER_OUT_SH1107_H + +#include "WipperSnapper_I2C_Driver_Out.h" +#include #include +#include #define WS_SH1107_DEFAULT_WIDTH \ 128 ///< Default width for a sh1107 128x64 display @@ -31,13 +34,21 @@ @brief Class that provides a driver interface for a SH1107 OLED Display */ -class dispDrvSh1107 : public dispDrvBase { +class WipperSnapper_I2C_Driver_Out_SH1107 + : public WipperSnapper_I2C_Driver_Out { + public: + /*******************************************************************************/ /*! - @brief Constructor for the SH1107 display driver. + @brief Constructor for an SH1107 OLED display. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. */ - dispDrvSh1107(TwoWire *i2c, uint16_t sensorAddress) - : dispDrvBase(i2c, sensorAddress), _display(nullptr) { + /*******************************************************************************/ + WipperSnapper_I2C_Driver_Out_SH1107(TwoWire *i2c, uint16_t sensorAddress) + : WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) { _i2c = i2c; _sensorAddress = sensorAddress; _width = WS_SH1107_DEFAULT_WIDTH; @@ -45,9 +56,9 @@ class dispDrvSh1107 : public dispDrvBase { } /*! - @brief Destructor for a SH1107 display driver. + @brief Destructor for a SH1107 OLED display. */ - ~dispDrvSh1107() { + ~WipperSnapper_I2C_Driver_Out_SH1107() { if (_display != nullptr) { _display->clearDisplay(); _display->display(); @@ -58,18 +69,14 @@ class dispDrvSh1107 : public dispDrvBase { } /*! - @brief Attempts to initialize the SSD1306 display driver. - @return True if the display was initialized successfully, false otherwise. + @brief Initializes the SH1107 display and begins I2C. + @returns True if initialized successfully, False otherwise. */ - bool begin() override { - if (!_i2c) - return false; - - // Attempt to create and allocate a SH1107 obj. + bool begin() { if (_width == OLED_128X64_WING_WIDTH && _height == OLED_128X64_WING_HEIGHT && _rotation == OLED_128X64_WING_ROTATION_90) { - // FeatherWing needs to be rotated 90deg and swap w/h ctor args + // featherwing needs to be rotated 90 degrees and swap w/h ctor args _display = new Adafruit_SH1107(_height, _width, _i2c); } else { _display = new Adafruit_SH1107(_width, _height, _i2c); @@ -93,34 +100,49 @@ class dispDrvSh1107 : public dispDrvBase { } /*! - @brief Sets the text size for the display. - @param s - The text size to set. - @note This method overrides the base class method to provide specific - functionality for the SSD1306 driver. + @brief Configures a SH1107 OLED display. Must be called before driver + begin() + @param width + The width of the display in pixels. + @param height + The height of the display in pixels. + @param text_size + The magnification factor for the text size. + @param rotation + The rotation of the display in degrees, default is 0. */ - void setTextSize(uint8_t s) override { - if (!_display) - return; - _text_sz = s; - _display->setTextSize(s); + void ConfigureSH1107(uint8_t width, uint8_t height, uint8_t text_size, + uint8_t rotation) { + _width = width; + _height = height; + _text_sz = text_size; + _rotation = + rotation % 90; // SH1107 requires rotation to be 0-3, not degrees } - - void setRotation(uint8_t r) override { - if (!_display) - return; - _rotation = r % 90; // constrain to 0-3 - _display->setRotation(r); + /*! + @brief Configures a SSD1306 OLED display. Must be called before driver + begin() - This is a fake function to match the SSD1306 interface. + @param width + The width of the display in pixels. + @param height + The height of the display in pixels. + @param text_size + The magnification factor for the text size. + @param rotation + The rotation of the display in degrees, default is 0. + */ + void ConfigureSSD1306(uint8_t width, uint8_t height, uint8_t text_size, + uint8_t rotation) { + // This is a SH1107, not a SSD1306, so we don't need to do anything here. + ConfigureSH1107(width, height, text_size, rotation); } /*! - @brief Writes a message to the display. - @param message - The message to write to the display. - @note This method overrides the base class method to provide specific - functionality for the SSD1306 driver. + @brief Writes a message to the SH1107 display. + @param message + The message to be displayed. */ - virtual void writeMessage(const char *message) override { + void WriteMessageSH1107(const char *message) { if (_display == nullptr) return; // Start with a fresh display buffer @@ -164,8 +186,23 @@ class dispDrvSh1107 : public dispDrvBase { } } -private: - Adafruit_SH1107 *_display; + /*! + @brief Writes a message to the fake "SSD1306" SH1107 display. + @param message + The message to be displayed. + */ + void WriteMessageSSD1306(const char *message) { + // This is a SH1107, not a SSD1306, so we just call the SH1107 write + WriteMessageSH1107(message); + } + +protected: + Adafruit_SH1107 *_display = + nullptr; ///< Pointer to the Adafruit_SH1107 object + uint8_t _width; ///< Width of the display in pixels + uint8_t _height; ///< Height of the display in pixels + uint8_t _rotation; ///< Rotation of the display (0-3) + uint8_t _text_sz; ///< Text size of the display }; -#endif // WS_DISP_DRV_SSD1306 \ No newline at end of file +#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_SH1107_H diff --git a/src/components/display/drivers/dispDrvSsd1306.h b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Ssd1306.h similarity index 51% rename from src/components/display/drivers/dispDrvSsd1306.h rename to src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Ssd1306.h index 1f81ede79..454a5852f 100644 --- a/src/components/display/drivers/dispDrvSsd1306.h +++ b/src/components/i2c/drivers/WipperSnapper_I2C_Driver_Out_Ssd1306.h @@ -1,21 +1,22 @@ /*! - * @file src/components/display/drivers/dispDrvSsd1306.h + * @file WipperSnapper_I2C_Driver_Out_Ssd1306.h * - * Driver for SSD1306-based OLED displays. + * Device driver for a SSD1306 OLED Display * * Adafruit invests time and resources providing this open source code, * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * - * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * Copyright (c) Brent Rubell for Adafruit Industries 2025 * - * BSD license, all text here must be included in any redistribution. + * MIT license, all text here must be included in any redistribution. * */ -#ifndef WS_DISP_DRV_SSD1306 -#define WS_DISP_DRV_SSD1306 -#include "dispDrvBase.h" +#ifndef WIPPERSNAPPER_I2C_DRIVER_OUT_SSD1306_H +#define WIPPERSNAPPER_I2C_DRIVER_OUT_SSD1306_H + +#include "WipperSnapper_I2C_Driver_Out.h" #include #include @@ -25,27 +26,35 @@ 64 ///< Default height for a ssd1306 128x64 display /*! - @brief Driver for SSD1306-based TFT displays. + @brief Class that provides a driver interface for a SSD1306 + OLED Display */ -class dispDrvSsd1306 : public dispDrvBase { +class WipperSnapper_I2C_Driver_Out_Ssd1306 + : public WipperSnapper_I2C_Driver_Out { + public: + /*******************************************************************************/ /*! - @brief Constructor for the SSD1306 display driver. - @param i2c - The I2C hardware interface, default is Wire. - @param sensorAddress - The I2C sensor's unique address. + @brief Constructor for a SSD1306 OLED display. + @param i2c + The I2C interface. + @param sensorAddress + 7-bit device address. */ - dispDrvSsd1306(TwoWire *i2c, uint16_t sensorAddress) - : dispDrvBase(i2c, sensorAddress), _display(nullptr) { + /*******************************************************************************/ + WipperSnapper_I2C_Driver_Out_Ssd1306(TwoWire *i2c, uint16_t sensorAddress) + : WipperSnapper_I2C_Driver_Out(i2c, sensorAddress) { _i2c = i2c; _sensorAddress = sensorAddress; _width = WS_SSD1306_DEFAULT_WIDTH; _height = WS_SSD1306_DEFAULT_HEIGHT; } - ~dispDrvSsd1306() { - if (_display) { + /*! + @brief Destructor for a SSD1306 OLED display. + */ + ~WipperSnapper_I2C_Driver_Out_Ssd1306() { + if (_display != nullptr) { _display->clearDisplay(); _display->display(); _display->ssd1306_command(SSD1306_DISPLAYOFF); @@ -55,12 +64,10 @@ class dispDrvSsd1306 : public dispDrvBase { } /*! - @brief Attempts to initialize the SSD1306 display driver. - @return True if the display was initialized successfully, false otherwise. + @brief Initializes the SSD1306 display and begins I2C. + @returns True if initialized successfully, False otherwise. */ - bool begin() override { - if (_i2c == nullptr) - return false; + bool begin() { // Attempt to create and allocate a SSD1306 obj. _display = new Adafruit_SSD1306(_width, _height, _i2c); if (!_display->begin(SSD1306_SWITCHCAPVCC, _sensorAddress)) @@ -78,27 +85,31 @@ class dispDrvSsd1306 : public dispDrvBase { } /*! - @brief Sets the text size for the display. - @param s - The text size to set. - @note This method overrides the base class method to provide specific - functionality for the SSD1306 driver. + @brief Configures a SSD1306 OLED display. Must be called before driver + begin() + @param width + The width of the display in pixels. + @param height + The height of the display in pixels. + @param text_size + The magnification factor for the text size. + @param rotation + The rotation of the display in degrees, default is 0. */ - void setTextSize(uint8_t s) override { - if (!_display) - return; - _text_sz = s; - _display->setTextSize(s); + void ConfigureSSD1306(uint8_t width, uint8_t height, uint8_t text_size, + uint8_t rotation = 0) { + _width = width; + _height = height; + _text_sz = text_size; + _rotation = rotation; } /*! - @brief Writes a message to the display. - @param message - The message to write to the display. - @note This method overrides the base class method to provide specific - functionality for the SSD1306 driver. + @brief Writes a message to the SSD1306 display. + @param message + The message to be displayed. */ - virtual void writeMessage(const char *message) override { + void WriteMessageSSD1306(const char *message) { if (_display == nullptr) return; @@ -106,6 +117,8 @@ class dispDrvSsd1306 : public dispDrvBase { // and settings int16_t y_idx = 0; _display->clearDisplay(); + _display->setTextSize(_text_sz); + _display->setTextColor(SSD1306_WHITE); _display->setCursor(0, y_idx); _display->display(); @@ -141,8 +154,13 @@ class dispDrvSsd1306 : public dispDrvBase { } } -private: - Adafruit_SSD1306 *_display; +protected: + Adafruit_SSD1306 *_display = + nullptr; ///< Pointer to the Adafruit_SSD1306 object + uint8_t _width; ///< Width of the display in pixels + uint8_t _height; ///< Height of the display in pixels + uint8_t _rotation; ///< Rotation of the display in degrees + uint8_t _text_sz; ///< Text size of the display }; -#endif // WS_DISP_DRV_SSD1306 \ No newline at end of file +#endif // WIPPERSNAPPER_I2C_DRIVER_OUT_SSD1306_H \ No newline at end of file diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index 874e06198..8d8cb3aea 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index bb7e4121b..d09c6efb8 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 514b94e58..39fe9aca8 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,12 +1,12 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. #endif -PB_BIND(wippersnapper_display_v1_SpiConfig, wippersnapper_display_v1_SpiConfig, AUTO) +PB_BIND(wippersnapper_display_v1_EpdSpiConfig, wippersnapper_display_v1_EpdSpiConfig, AUTO) PB_BIND(wippersnapper_display_v1_EPDConfig, wippersnapper_display_v1_EPDConfig, AUTO) @@ -15,22 +15,13 @@ PB_BIND(wippersnapper_display_v1_EPDConfig, wippersnapper_display_v1_EPDConfig, PB_BIND(wippersnapper_display_v1_EPDWriteOptions, wippersnapper_display_v1_EPDWriteOptions, AUTO) -PB_BIND(wippersnapper_display_v1_TftConfig, wippersnapper_display_v1_TftConfig, AUTO) - - -PB_BIND(wippersnapper_display_v1_I2cConfig, wippersnapper_display_v1_I2cConfig, 2) - +PB_BIND(wippersnapper_display_v1_TftSpiConfig, wippersnapper_display_v1_TftSpiConfig, AUTO) -PB_BIND(wippersnapper_display_v1_OledConfig, wippersnapper_display_v1_OledConfig, AUTO) - -PB_BIND(wippersnapper_display_v1_LEDBackpackConfig, wippersnapper_display_v1_LEDBackpackConfig, AUTO) - - -PB_BIND(wippersnapper_display_v1_CharLCDConfig, wippersnapper_display_v1_CharLCDConfig, AUTO) +PB_BIND(wippersnapper_display_v1_TftConfig, wippersnapper_display_v1_TftConfig, AUTO) -PB_BIND(wippersnapper_display_v1_DisplayAddOrReplace, wippersnapper_display_v1_DisplayAddOrReplace, 2) +PB_BIND(wippersnapper_display_v1_DisplayAddOrReplace, wippersnapper_display_v1_DisplayAddOrReplace, AUTO) PB_BIND(wippersnapper_display_v1_DisplayRemove, wippersnapper_display_v1_DisplayRemove, AUTO) diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index a01767f1a..1c31c7661 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -26,11 +26,6 @@ typedef enum _wippersnapper_display_v1_EPDMode { } wippersnapper_display_v1_EPDMode; /* Struct definitions */ -typedef struct _wippersnapper_display_v1_CharLCDConfig { - uint32_t rows; - uint32_t columns; -} wippersnapper_display_v1_CharLCDConfig; - typedef struct _wippersnapper_display_v1_DisplayAddedorReplaced { char name[64]; bool did_add; @@ -53,33 +48,14 @@ typedef struct _wippersnapper_display_v1_EPDWriteOptions { int32_t text_size; } wippersnapper_display_v1_EPDWriteOptions; -typedef struct _wippersnapper_display_v1_I2cConfig { - bool has_i2c; - wippersnapper_i2c_v1_I2CDeviceInitRequest i2c; -} wippersnapper_display_v1_I2cConfig; - -typedef struct _wippersnapper_display_v1_LEDBackpackConfig { - int32_t brightness; - uint32_t alignment; -} wippersnapper_display_v1_LEDBackpackConfig; - -typedef struct _wippersnapper_display_v1_OledConfig { - uint32_t width; - uint32_t height; - int32_t text_size; -} wippersnapper_display_v1_OledConfig; - -typedef struct _wippersnapper_display_v1_SpiConfig { +typedef struct _wippersnapper_display_v1_EpdSpiConfig { int32_t bus; char pin_dc[6]; char pin_rst[6]; char pin_cs[6]; char pin_sram_cs[6]; char pin_busy[6]; - char pin_mosi[6]; - char pin_sck[6]; - char pin_miso[6]; -} wippersnapper_display_v1_SpiConfig; +} wippersnapper_display_v1_EpdSpiConfig; typedef struct _wippersnapper_display_v1_TftConfig { int32_t width; @@ -87,21 +63,28 @@ typedef struct _wippersnapper_display_v1_TftConfig { int32_t rotation; } wippersnapper_display_v1_TftConfig; +typedef struct _wippersnapper_display_v1_TftSpiConfig { + int32_t bus; + char pin_cs[6]; + char pin_dc[6]; + char pin_mosi[6]; + char pin_sck[6]; + char pin_rst[6]; + char pin_miso[6]; +} wippersnapper_display_v1_TftSpiConfig; + typedef struct _wippersnapper_display_v1_DisplayAddOrReplace { wippersnapper_display_v1_DisplayType type; char name[64]; pb_size_t which_interface_type; union { - wippersnapper_display_v1_SpiConfig cfg_spi; - wippersnapper_display_v1_I2cConfig cfg_i2c; + wippersnapper_display_v1_EpdSpiConfig spi_epd; + wippersnapper_display_v1_TftSpiConfig spi_tft; } interface_type; pb_size_t which_config; union { wippersnapper_display_v1_EPDConfig config_epd; wippersnapper_display_v1_TftConfig config_tft; - wippersnapper_display_v1_OledConfig config_oled; - wippersnapper_display_v1_LEDBackpackConfig config_led_backpack; - wippersnapper_display_v1_CharLCDConfig config_char_lcd; } config; } wippersnapper_display_v1_DisplayAddOrReplace; @@ -130,36 +113,28 @@ extern "C" { #endif /* Initializer values for message structs */ -#define wippersnapper_display_v1_SpiConfig_init_default {0, "", "", "", "", "", "", "", ""} +#define wippersnapper_display_v1_EpdSpiConfig_init_default {0, "", "", "", "", ""} #define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN} #define wippersnapper_display_v1_EPDWriteOptions_init_default {0} +#define wippersnapper_display_v1_TftSpiConfig_init_default {0, "", "", "", "", "", ""} #define wippersnapper_display_v1_TftConfig_init_default {0, 0, 0} -#define wippersnapper_display_v1_I2cConfig_init_default {false, wippersnapper_i2c_v1_I2CDeviceInitRequest_init_default} -#define wippersnapper_display_v1_OledConfig_init_default {0, 0, 0} -#define wippersnapper_display_v1_LEDBackpackConfig_init_default {0, 0} -#define wippersnapper_display_v1_CharLCDConfig_init_default {0, 0} -#define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_SpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} +#define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} #define wippersnapper_display_v1_DisplayRemove_init_default {""} #define wippersnapper_display_v1_DisplayWrite_init_default {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_default}} #define wippersnapper_display_v1_DisplayAddedorReplaced_init_default {"", 0} #define wippersnapper_display_v1_DisplayRemoved_init_default {"", 0} -#define wippersnapper_display_v1_SpiConfig_init_zero {0, "", "", "", "", "", "", "", ""} +#define wippersnapper_display_v1_EpdSpiConfig_init_zero {0, "", "", "", "", ""} #define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN} #define wippersnapper_display_v1_EPDWriteOptions_init_zero {0} +#define wippersnapper_display_v1_TftSpiConfig_init_zero {0, "", "", "", "", "", ""} #define wippersnapper_display_v1_TftConfig_init_zero {0, 0, 0} -#define wippersnapper_display_v1_I2cConfig_init_zero {false, wippersnapper_i2c_v1_I2CDeviceInitRequest_init_zero} -#define wippersnapper_display_v1_OledConfig_init_zero {0, 0, 0} -#define wippersnapper_display_v1_LEDBackpackConfig_init_zero {0, 0} -#define wippersnapper_display_v1_CharLCDConfig_init_zero {0, 0} -#define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_SpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} +#define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} #define wippersnapper_display_v1_DisplayRemove_init_zero {""} #define wippersnapper_display_v1_DisplayWrite_init_zero {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_zero}} #define wippersnapper_display_v1_DisplayAddedorReplaced_init_zero {"", 0} #define wippersnapper_display_v1_DisplayRemoved_init_zero {"", 0} /* Field tags (for use in manual encoding/decoding) */ -#define wippersnapper_display_v1_CharLCDConfig_rows_tag 1 -#define wippersnapper_display_v1_CharLCDConfig_columns_tag 2 #define wippersnapper_display_v1_DisplayAddedorReplaced_name_tag 1 #define wippersnapper_display_v1_DisplayAddedorReplaced_did_add_tag 2 #define wippersnapper_display_v1_DisplayRemove_name_tag 1 @@ -167,50 +142,42 @@ extern "C" { #define wippersnapper_display_v1_DisplayRemoved_did_remove_tag 2 #define wippersnapper_display_v1_EPDConfig_mode_tag 1 #define wippersnapper_display_v1_EPDWriteOptions_text_size_tag 1 -#define wippersnapper_display_v1_I2cConfig_i2c_tag 1 -#define wippersnapper_display_v1_LEDBackpackConfig_brightness_tag 1 -#define wippersnapper_display_v1_LEDBackpackConfig_alignment_tag 2 -#define wippersnapper_display_v1_OledConfig_width_tag 1 -#define wippersnapper_display_v1_OledConfig_height_tag 2 -#define wippersnapper_display_v1_OledConfig_text_size_tag 3 -#define wippersnapper_display_v1_SpiConfig_bus_tag 1 -#define wippersnapper_display_v1_SpiConfig_pin_dc_tag 2 -#define wippersnapper_display_v1_SpiConfig_pin_rst_tag 3 -#define wippersnapper_display_v1_SpiConfig_pin_cs_tag 4 -#define wippersnapper_display_v1_SpiConfig_pin_sram_cs_tag 5 -#define wippersnapper_display_v1_SpiConfig_pin_busy_tag 6 -#define wippersnapper_display_v1_SpiConfig_pin_mosi_tag 7 -#define wippersnapper_display_v1_SpiConfig_pin_sck_tag 8 -#define wippersnapper_display_v1_SpiConfig_pin_miso_tag 9 +#define wippersnapper_display_v1_EpdSpiConfig_bus_tag 1 +#define wippersnapper_display_v1_EpdSpiConfig_pin_dc_tag 2 +#define wippersnapper_display_v1_EpdSpiConfig_pin_rst_tag 3 +#define wippersnapper_display_v1_EpdSpiConfig_pin_cs_tag 4 +#define wippersnapper_display_v1_EpdSpiConfig_pin_sram_cs_tag 5 +#define wippersnapper_display_v1_EpdSpiConfig_pin_busy_tag 6 #define wippersnapper_display_v1_TftConfig_width_tag 1 #define wippersnapper_display_v1_TftConfig_height_tag 2 #define wippersnapper_display_v1_TftConfig_rotation_tag 3 +#define wippersnapper_display_v1_TftSpiConfig_bus_tag 1 +#define wippersnapper_display_v1_TftSpiConfig_pin_cs_tag 2 +#define wippersnapper_display_v1_TftSpiConfig_pin_dc_tag 3 +#define wippersnapper_display_v1_TftSpiConfig_pin_mosi_tag 4 +#define wippersnapper_display_v1_TftSpiConfig_pin_sck_tag 5 +#define wippersnapper_display_v1_TftSpiConfig_pin_rst_tag 6 +#define wippersnapper_display_v1_TftSpiConfig_pin_miso_tag 7 #define wippersnapper_display_v1_DisplayAddOrReplace_type_tag 1 #define wippersnapper_display_v1_DisplayAddOrReplace_name_tag 2 -#define wippersnapper_display_v1_DisplayAddOrReplace_cfg_spi_tag 3 -#define wippersnapper_display_v1_DisplayAddOrReplace_cfg_i2c_tag 4 +#define wippersnapper_display_v1_DisplayAddOrReplace_spi_epd_tag 3 +#define wippersnapper_display_v1_DisplayAddOrReplace_spi_tft_tag 4 #define wippersnapper_display_v1_DisplayAddOrReplace_config_epd_tag 5 #define wippersnapper_display_v1_DisplayAddOrReplace_config_tft_tag 6 -#define wippersnapper_display_v1_DisplayAddOrReplace_config_oled_tag 7 -#define wippersnapper_display_v1_DisplayAddOrReplace_config_led_backpack_tag 8 -#define wippersnapper_display_v1_DisplayAddOrReplace_config_char_lcd_tag 9 #define wippersnapper_display_v1_DisplayWrite_name_tag 1 #define wippersnapper_display_v1_DisplayWrite_message_tag 2 #define wippersnapper_display_v1_DisplayWrite_epd_options_tag 3 /* Struct field encoding specification for nanopb */ -#define wippersnapper_display_v1_SpiConfig_FIELDLIST(X, a) \ +#define wippersnapper_display_v1_EpdSpiConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, bus, 1) \ X(a, STATIC, SINGULAR, STRING, pin_dc, 2) \ X(a, STATIC, SINGULAR, STRING, pin_rst, 3) \ X(a, STATIC, SINGULAR, STRING, pin_cs, 4) \ X(a, STATIC, SINGULAR, STRING, pin_sram_cs, 5) \ -X(a, STATIC, SINGULAR, STRING, pin_busy, 6) \ -X(a, STATIC, SINGULAR, STRING, pin_mosi, 7) \ -X(a, STATIC, SINGULAR, STRING, pin_sck, 8) \ -X(a, STATIC, SINGULAR, STRING, pin_miso, 9) -#define wippersnapper_display_v1_SpiConfig_CALLBACK NULL -#define wippersnapper_display_v1_SpiConfig_DEFAULT NULL +X(a, STATIC, SINGULAR, STRING, pin_busy, 6) +#define wippersnapper_display_v1_EpdSpiConfig_CALLBACK NULL +#define wippersnapper_display_v1_EpdSpiConfig_DEFAULT NULL #define wippersnapper_display_v1_EPDConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, mode, 1) @@ -222,6 +189,17 @@ X(a, STATIC, SINGULAR, INT32, text_size, 1) #define wippersnapper_display_v1_EPDWriteOptions_CALLBACK NULL #define wippersnapper_display_v1_EPDWriteOptions_DEFAULT NULL +#define wippersnapper_display_v1_TftSpiConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, bus, 1) \ +X(a, STATIC, SINGULAR, STRING, pin_cs, 2) \ +X(a, STATIC, SINGULAR, STRING, pin_dc, 3) \ +X(a, STATIC, SINGULAR, STRING, pin_mosi, 4) \ +X(a, STATIC, SINGULAR, STRING, pin_sck, 5) \ +X(a, STATIC, SINGULAR, STRING, pin_rst, 6) \ +X(a, STATIC, SINGULAR, STRING, pin_miso, 7) +#define wippersnapper_display_v1_TftSpiConfig_CALLBACK NULL +#define wippersnapper_display_v1_TftSpiConfig_DEFAULT NULL + #define wippersnapper_display_v1_TftConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, width, 1) \ X(a, STATIC, SINGULAR, INT32, height, 2) \ @@ -229,50 +207,19 @@ X(a, STATIC, SINGULAR, INT32, rotation, 3) #define wippersnapper_display_v1_TftConfig_CALLBACK NULL #define wippersnapper_display_v1_TftConfig_DEFAULT NULL -#define wippersnapper_display_v1_I2cConfig_FIELDLIST(X, a) \ -X(a, STATIC, OPTIONAL, MESSAGE, i2c, 1) -#define wippersnapper_display_v1_I2cConfig_CALLBACK NULL -#define wippersnapper_display_v1_I2cConfig_DEFAULT NULL -#define wippersnapper_display_v1_I2cConfig_i2c_MSGTYPE wippersnapper_i2c_v1_I2CDeviceInitRequest - -#define wippersnapper_display_v1_OledConfig_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, width, 1) \ -X(a, STATIC, SINGULAR, UINT32, height, 2) \ -X(a, STATIC, SINGULAR, INT32, text_size, 3) -#define wippersnapper_display_v1_OledConfig_CALLBACK NULL -#define wippersnapper_display_v1_OledConfig_DEFAULT NULL - -#define wippersnapper_display_v1_LEDBackpackConfig_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, INT32, brightness, 1) \ -X(a, STATIC, SINGULAR, UINT32, alignment, 2) -#define wippersnapper_display_v1_LEDBackpackConfig_CALLBACK NULL -#define wippersnapper_display_v1_LEDBackpackConfig_DEFAULT NULL - -#define wippersnapper_display_v1_CharLCDConfig_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UINT32, rows, 1) \ -X(a, STATIC, SINGULAR, UINT32, columns, 2) -#define wippersnapper_display_v1_CharLCDConfig_CALLBACK NULL -#define wippersnapper_display_v1_CharLCDConfig_DEFAULT NULL - #define wippersnapper_display_v1_DisplayAddOrReplace_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, type, 1) \ X(a, STATIC, SINGULAR, STRING, name, 2) \ -X(a, STATIC, ONEOF, MESSAGE, (interface_type,cfg_spi,interface_type.cfg_spi), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (interface_type,cfg_i2c,interface_type.cfg_i2c), 4) \ +X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_epd,interface_type.spi_epd), 3) \ +X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_tft,interface_type.spi_tft), 4) \ X(a, STATIC, ONEOF, MESSAGE, (config,config_epd,config.config_epd), 5) \ -X(a, STATIC, ONEOF, MESSAGE, (config,config_tft,config.config_tft), 6) \ -X(a, STATIC, ONEOF, MESSAGE, (config,config_oled,config.config_oled), 7) \ -X(a, STATIC, ONEOF, MESSAGE, (config,config_led_backpack,config.config_led_backpack), 8) \ -X(a, STATIC, ONEOF, MESSAGE, (config,config_char_lcd,config.config_char_lcd), 9) +X(a, STATIC, ONEOF, MESSAGE, (config,config_tft,config.config_tft), 6) #define wippersnapper_display_v1_DisplayAddOrReplace_CALLBACK NULL #define wippersnapper_display_v1_DisplayAddOrReplace_DEFAULT NULL -#define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_cfg_spi_MSGTYPE wippersnapper_display_v1_SpiConfig -#define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_cfg_i2c_MSGTYPE wippersnapper_display_v1_I2cConfig +#define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_spi_epd_MSGTYPE wippersnapper_display_v1_EpdSpiConfig +#define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_spi_tft_MSGTYPE wippersnapper_display_v1_TftSpiConfig #define wippersnapper_display_v1_DisplayAddOrReplace_config_config_epd_MSGTYPE wippersnapper_display_v1_EPDConfig #define wippersnapper_display_v1_DisplayAddOrReplace_config_config_tft_MSGTYPE wippersnapper_display_v1_TftConfig -#define wippersnapper_display_v1_DisplayAddOrReplace_config_config_oled_MSGTYPE wippersnapper_display_v1_OledConfig -#define wippersnapper_display_v1_DisplayAddOrReplace_config_config_led_backpack_MSGTYPE wippersnapper_display_v1_LEDBackpackConfig -#define wippersnapper_display_v1_DisplayAddOrReplace_config_config_char_lcd_MSGTYPE wippersnapper_display_v1_CharLCDConfig #define wippersnapper_display_v1_DisplayRemove_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, name, 1) @@ -299,14 +246,11 @@ X(a, STATIC, SINGULAR, BOOL, did_remove, 2) #define wippersnapper_display_v1_DisplayRemoved_CALLBACK NULL #define wippersnapper_display_v1_DisplayRemoved_DEFAULT NULL -extern const pb_msgdesc_t wippersnapper_display_v1_SpiConfig_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_EpdSpiConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_EPDConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_EPDWriteOptions_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_TftSpiConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_TftConfig_msg; -extern const pb_msgdesc_t wippersnapper_display_v1_I2cConfig_msg; -extern const pb_msgdesc_t wippersnapper_display_v1_OledConfig_msg; -extern const pb_msgdesc_t wippersnapper_display_v1_LEDBackpackConfig_msg; -extern const pb_msgdesc_t wippersnapper_display_v1_CharLCDConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayAddOrReplace_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemove_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayWrite_msg; @@ -314,14 +258,11 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayAddedorReplaced_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ -#define wippersnapper_display_v1_SpiConfig_fields &wippersnapper_display_v1_SpiConfig_msg +#define wippersnapper_display_v1_EpdSpiConfig_fields &wippersnapper_display_v1_EpdSpiConfig_msg #define wippersnapper_display_v1_EPDConfig_fields &wippersnapper_display_v1_EPDConfig_msg #define wippersnapper_display_v1_EPDWriteOptions_fields &wippersnapper_display_v1_EPDWriteOptions_msg +#define wippersnapper_display_v1_TftSpiConfig_fields &wippersnapper_display_v1_TftSpiConfig_msg #define wippersnapper_display_v1_TftConfig_fields &wippersnapper_display_v1_TftConfig_msg -#define wippersnapper_display_v1_I2cConfig_fields &wippersnapper_display_v1_I2cConfig_msg -#define wippersnapper_display_v1_OledConfig_fields &wippersnapper_display_v1_OledConfig_msg -#define wippersnapper_display_v1_LEDBackpackConfig_fields &wippersnapper_display_v1_LEDBackpackConfig_msg -#define wippersnapper_display_v1_CharLCDConfig_fields &wippersnapper_display_v1_CharLCDConfig_msg #define wippersnapper_display_v1_DisplayAddOrReplace_fields &wippersnapper_display_v1_DisplayAddOrReplace_msg #define wippersnapper_display_v1_DisplayRemove_fields &wippersnapper_display_v1_DisplayRemove_msg #define wippersnapper_display_v1_DisplayWrite_fields &wippersnapper_display_v1_DisplayWrite_msg @@ -329,15 +270,12 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; #define wippersnapper_display_v1_DisplayRemoved_fields &wippersnapper_display_v1_DisplayRemoved_msg /* Maximum encoded size of messages (where known) */ -#define wippersnapper_display_v1_SpiConfig_size 67 +#define wippersnapper_display_v1_EpdSpiConfig_size 46 #define wippersnapper_display_v1_EPDConfig_size 2 #define wippersnapper_display_v1_EPDWriteOptions_size 11 +#define wippersnapper_display_v1_TftSpiConfig_size 53 #define wippersnapper_display_v1_TftConfig_size 33 -#define wippersnapper_display_v1_I2cConfig_size 469 -#define wippersnapper_display_v1_OledConfig_size 23 -#define wippersnapper_display_v1_LEDBackpackConfig_size 17 -#define wippersnapper_display_v1_CharLCDConfig_size 12 -#define wippersnapper_display_v1_DisplayAddOrReplace_size 574 +#define wippersnapper_display_v1_DisplayAddOrReplace_size 157 #define wippersnapper_display_v1_DisplayRemove_size 65 #define wippersnapper_display_v1_DisplayWrite_size 1104 #define wippersnapper_display_v1_DisplayAddedorReplaced_size 67 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index ec21e3efd..2b844940b 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index a2834afd2..84a16a5de 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index 375fa72cf..9a2cd926d 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -51,6 +51,32 @@ PB_BIND(wippersnapper_i2c_v1_SensorEvent, wippersnapper_i2c_v1_SensorEvent, AUTO PB_BIND(wippersnapper_i2c_v1_I2CDeviceEvent, wippersnapper_i2c_v1_I2CDeviceEvent, AUTO) +PB_BIND(wippersnapper_i2c_v1_I2CDeviceOutputWrite, wippersnapper_i2c_v1_I2CDeviceOutputWrite, 2) + + +PB_BIND(wippersnapper_i2c_v1_LEDBackpackConfig, wippersnapper_i2c_v1_LEDBackpackConfig, AUTO) + + +PB_BIND(wippersnapper_i2c_v1_CharLCDConfig, wippersnapper_i2c_v1_CharLCDConfig, AUTO) + + +PB_BIND(wippersnapper_i2c_v1_SSD1306Config, wippersnapper_i2c_v1_SSD1306Config, AUTO) + + +PB_BIND(wippersnapper_i2c_v1_I2COutputAdd, wippersnapper_i2c_v1_I2COutputAdd, AUTO) + + +PB_BIND(wippersnapper_i2c_v1_LEDBackpackWrite, wippersnapper_i2c_v1_LEDBackpackWrite, AUTO) + + +PB_BIND(wippersnapper_i2c_v1_CharLCDWrite, wippersnapper_i2c_v1_CharLCDWrite, AUTO) + + +PB_BIND(wippersnapper_i2c_v1_SSD1306Write, wippersnapper_i2c_v1_SSD1306Write, 2) + + + + diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 6b1d7b1b3..0afda161c 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED @@ -60,11 +60,33 @@ typedef enum _wippersnapper_i2c_v1_SensorType { wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_TVOC = 35 } wippersnapper_i2c_v1_SensorType; +typedef enum _wippersnapper_i2c_v1_LEDBackpackAlignment { + wippersnapper_i2c_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_UNSPECIFIED = 0, + wippersnapper_i2c_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_LEFT = 1, + wippersnapper_i2c_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT = 2 +} wippersnapper_i2c_v1_LEDBackpackAlignment; + +typedef enum _wippersnapper_i2c_v1_SSD1306TextSize { + wippersnapper_i2c_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_UNSPECIFIED = 0, + wippersnapper_i2c_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_1 = 1, + wippersnapper_i2c_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_2 = 2 +} wippersnapper_i2c_v1_SSD1306TextSize; + /* Struct definitions */ typedef struct _wippersnapper_i2c_v1_I2CDeviceInitRequests { pb_callback_t list; } wippersnapper_i2c_v1_I2CDeviceInitRequests; +typedef struct _wippersnapper_i2c_v1_CharLCDConfig { + uint32_t rows; + uint32_t columns; +} wippersnapper_i2c_v1_CharLCDConfig; + +typedef struct _wippersnapper_i2c_v1_CharLCDWrite { + char message[128]; + bool enable_backlight; +} wippersnapper_i2c_v1_CharLCDWrite; + typedef struct _wippersnapper_i2c_v1_I2CBusInitRequest { int32_t i2c_pin_scl; int32_t i2c_pin_sda; @@ -112,6 +134,25 @@ typedef struct _wippersnapper_i2c_v1_I2CDeviceUpdateResponse { wippersnapper_i2c_v1_BusResponse bus_response; } wippersnapper_i2c_v1_I2CDeviceUpdateResponse; +typedef struct _wippersnapper_i2c_v1_LEDBackpackConfig { + int32_t brightness; + wippersnapper_i2c_v1_LEDBackpackAlignment alignment; +} wippersnapper_i2c_v1_LEDBackpackConfig; + +typedef struct _wippersnapper_i2c_v1_LEDBackpackWrite { + char message[128]; +} wippersnapper_i2c_v1_LEDBackpackWrite; + +typedef struct _wippersnapper_i2c_v1_SSD1306Config { + uint32_t width; + uint32_t height; + wippersnapper_i2c_v1_SSD1306TextSize text_size; +} wippersnapper_i2c_v1_SSD1306Config; + +typedef struct _wippersnapper_i2c_v1_SSD1306Write { + char message[256]; +} wippersnapper_i2c_v1_SSD1306Write; + typedef struct _wippersnapper_i2c_v1_SensorEvent { wippersnapper_i2c_v1_SensorType type; float value; @@ -129,23 +170,46 @@ typedef struct _wippersnapper_i2c_v1_I2CDeviceEvent { wippersnapper_i2c_v1_SensorEvent sensor_event[15]; } wippersnapper_i2c_v1_I2CDeviceEvent; -typedef struct _wippersnapper_i2c_v1_I2CDeviceInitRequest { +typedef struct _wippersnapper_i2c_v1_I2CDeviceOutputWrite { + uint32_t i2c_device_address; + char i2c_device_name[256]; + pb_size_t which_output_msg; + union { + wippersnapper_i2c_v1_LEDBackpackWrite write_led_backpack; + wippersnapper_i2c_v1_CharLCDWrite write_char_lcd; + wippersnapper_i2c_v1_SSD1306Write write_ssd1306; + } output_msg; +} wippersnapper_i2c_v1_I2CDeviceOutputWrite; + +typedef struct _wippersnapper_i2c_v1_I2CDeviceUpdateRequest { int32_t i2c_port_number; - bool has_i2c_bus_init_req; - wippersnapper_i2c_v1_I2CBusInitRequest i2c_bus_init_req; uint32_t i2c_device_address; char i2c_device_name[256]; pb_size_t i2c_device_properties_count; wippersnapper_i2c_v1_I2CDeviceSensorProperties i2c_device_properties[15]; -} wippersnapper_i2c_v1_I2CDeviceInitRequest; +} wippersnapper_i2c_v1_I2CDeviceUpdateRequest; -typedef struct _wippersnapper_i2c_v1_I2CDeviceUpdateRequest { +typedef struct _wippersnapper_i2c_v1_I2COutputAdd { + pb_size_t which_config; + union { + wippersnapper_i2c_v1_LEDBackpackConfig led_backpack_config; + wippersnapper_i2c_v1_CharLCDConfig char_lcd_config; + wippersnapper_i2c_v1_SSD1306Config ssd1306_config; + } config; +} wippersnapper_i2c_v1_I2COutputAdd; + +typedef struct _wippersnapper_i2c_v1_I2CDeviceInitRequest { int32_t i2c_port_number; + bool has_i2c_bus_init_req; + wippersnapper_i2c_v1_I2CBusInitRequest i2c_bus_init_req; uint32_t i2c_device_address; char i2c_device_name[256]; pb_size_t i2c_device_properties_count; wippersnapper_i2c_v1_I2CDeviceSensorProperties i2c_device_properties[15]; -} wippersnapper_i2c_v1_I2CDeviceUpdateRequest; + bool is_output_device; + bool has_i2c_output_add; + wippersnapper_i2c_v1_I2COutputAdd i2c_output_add; +} wippersnapper_i2c_v1_I2CDeviceInitRequest; /* Helper constants for enums */ @@ -157,6 +221,14 @@ typedef struct _wippersnapper_i2c_v1_I2CDeviceUpdateRequest { #define _wippersnapper_i2c_v1_SensorType_MAX wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_TVOC #define _wippersnapper_i2c_v1_SensorType_ARRAYSIZE ((wippersnapper_i2c_v1_SensorType)(wippersnapper_i2c_v1_SensorType_SENSOR_TYPE_TVOC+1)) +#define _wippersnapper_i2c_v1_LEDBackpackAlignment_MIN wippersnapper_i2c_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_UNSPECIFIED +#define _wippersnapper_i2c_v1_LEDBackpackAlignment_MAX wippersnapper_i2c_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT +#define _wippersnapper_i2c_v1_LEDBackpackAlignment_ARRAYSIZE ((wippersnapper_i2c_v1_LEDBackpackAlignment)(wippersnapper_i2c_v1_LEDBackpackAlignment_LED_BACKPACK_ALIGNMENT_RIGHT+1)) + +#define _wippersnapper_i2c_v1_SSD1306TextSize_MIN wippersnapper_i2c_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_UNSPECIFIED +#define _wippersnapper_i2c_v1_SSD1306TextSize_MAX wippersnapper_i2c_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_2 +#define _wippersnapper_i2c_v1_SSD1306TextSize_ARRAYSIZE ((wippersnapper_i2c_v1_SSD1306TextSize)(wippersnapper_i2c_v1_SSD1306TextSize_SSD1306_TEXT_SIZE_2+1)) + #ifdef __cplusplus extern "C" { @@ -170,7 +242,7 @@ extern "C" { #define wippersnapper_i2c_v1_I2CBusScanResponse_init_default {0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, _wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default {_wippersnapper_i2c_v1_SensorType_MIN, 0} #define wippersnapper_i2c_v1_I2CDeviceInitRequests_init_default {{{NULL}, NULL}} -#define wippersnapper_i2c_v1_I2CDeviceInitRequest_init_default {0, false, wippersnapper_i2c_v1_I2CBusInitRequest_init_default, 0, "", 0, {wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default}} +#define wippersnapper_i2c_v1_I2CDeviceInitRequest_init_default {0, false, wippersnapper_i2c_v1_I2CBusInitRequest_init_default, 0, "", 0, {wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default}, 0, false, wippersnapper_i2c_v1_I2COutputAdd_init_default} #define wippersnapper_i2c_v1_I2CDeviceInitResponse_init_default {0, _wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_init_default {0, 0, "", 0, {wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_default}} #define wippersnapper_i2c_v1_I2CDeviceUpdateResponse_init_default {0, _wippersnapper_i2c_v1_BusResponse_MIN} @@ -178,6 +250,14 @@ extern "C" { #define wippersnapper_i2c_v1_I2CDeviceDeinitResponse_init_default {0, _wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_SensorEvent_init_default {_wippersnapper_i2c_v1_SensorType_MIN, 0} #define wippersnapper_i2c_v1_I2CDeviceEvent_init_default {0, 0, {wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default, wippersnapper_i2c_v1_SensorEvent_init_default}} +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_init_default {0, "", 0, {wippersnapper_i2c_v1_LEDBackpackWrite_init_default}} +#define wippersnapper_i2c_v1_LEDBackpackConfig_init_default {0, _wippersnapper_i2c_v1_LEDBackpackAlignment_MIN} +#define wippersnapper_i2c_v1_CharLCDConfig_init_default {0, 0} +#define wippersnapper_i2c_v1_SSD1306Config_init_default {0, 0, _wippersnapper_i2c_v1_SSD1306TextSize_MIN} +#define wippersnapper_i2c_v1_I2COutputAdd_init_default {0, {wippersnapper_i2c_v1_LEDBackpackConfig_init_default}} +#define wippersnapper_i2c_v1_LEDBackpackWrite_init_default {""} +#define wippersnapper_i2c_v1_CharLCDWrite_init_default {"", 0} +#define wippersnapper_i2c_v1_SSD1306Write_init_default {""} #define wippersnapper_i2c_v1_I2CBusInitRequest_init_zero {0, 0, 0, 0} #define wippersnapper_i2c_v1_I2CBusInitResponse_init_zero {_wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_I2CBusSetFrequency_init_zero {0, 0} @@ -185,7 +265,7 @@ extern "C" { #define wippersnapper_i2c_v1_I2CBusScanResponse_init_zero {0, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, _wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero {_wippersnapper_i2c_v1_SensorType_MIN, 0} #define wippersnapper_i2c_v1_I2CDeviceInitRequests_init_zero {{{NULL}, NULL}} -#define wippersnapper_i2c_v1_I2CDeviceInitRequest_init_zero {0, false, wippersnapper_i2c_v1_I2CBusInitRequest_init_zero, 0, "", 0, {wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero}} +#define wippersnapper_i2c_v1_I2CDeviceInitRequest_init_zero {0, false, wippersnapper_i2c_v1_I2CBusInitRequest_init_zero, 0, "", 0, {wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero}, 0, false, wippersnapper_i2c_v1_I2COutputAdd_init_zero} #define wippersnapper_i2c_v1_I2CDeviceInitResponse_init_zero {0, _wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_init_zero {0, 0, "", 0, {wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero, wippersnapper_i2c_v1_I2CDeviceSensorProperties_init_zero}} #define wippersnapper_i2c_v1_I2CDeviceUpdateResponse_init_zero {0, _wippersnapper_i2c_v1_BusResponse_MIN} @@ -193,9 +273,21 @@ extern "C" { #define wippersnapper_i2c_v1_I2CDeviceDeinitResponse_init_zero {0, _wippersnapper_i2c_v1_BusResponse_MIN} #define wippersnapper_i2c_v1_SensorEvent_init_zero {_wippersnapper_i2c_v1_SensorType_MIN, 0} #define wippersnapper_i2c_v1_I2CDeviceEvent_init_zero {0, 0, {wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero, wippersnapper_i2c_v1_SensorEvent_init_zero}} +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_init_zero {0, "", 0, {wippersnapper_i2c_v1_LEDBackpackWrite_init_zero}} +#define wippersnapper_i2c_v1_LEDBackpackConfig_init_zero {0, _wippersnapper_i2c_v1_LEDBackpackAlignment_MIN} +#define wippersnapper_i2c_v1_CharLCDConfig_init_zero {0, 0} +#define wippersnapper_i2c_v1_SSD1306Config_init_zero {0, 0, _wippersnapper_i2c_v1_SSD1306TextSize_MIN} +#define wippersnapper_i2c_v1_I2COutputAdd_init_zero {0, {wippersnapper_i2c_v1_LEDBackpackConfig_init_zero}} +#define wippersnapper_i2c_v1_LEDBackpackWrite_init_zero {""} +#define wippersnapper_i2c_v1_CharLCDWrite_init_zero {"", 0} +#define wippersnapper_i2c_v1_SSD1306Write_init_zero {""} /* Field tags (for use in manual encoding/decoding) */ #define wippersnapper_i2c_v1_I2CDeviceInitRequests_list_tag 1 +#define wippersnapper_i2c_v1_CharLCDConfig_rows_tag 1 +#define wippersnapper_i2c_v1_CharLCDConfig_columns_tag 2 +#define wippersnapper_i2c_v1_CharLCDWrite_message_tag 1 +#define wippersnapper_i2c_v1_CharLCDWrite_enable_backlight_tag 2 #define wippersnapper_i2c_v1_I2CBusInitRequest_i2c_pin_scl_tag 1 #define wippersnapper_i2c_v1_I2CBusInitRequest_i2c_pin_sda_tag 2 #define wippersnapper_i2c_v1_I2CBusInitRequest_i2c_frequency_tag 3 @@ -215,21 +307,38 @@ extern "C" { #define wippersnapper_i2c_v1_I2CDeviceSensorProperties_sensor_period_tag 2 #define wippersnapper_i2c_v1_I2CDeviceUpdateResponse_i2c_device_address_tag 1 #define wippersnapper_i2c_v1_I2CDeviceUpdateResponse_bus_response_tag 3 +#define wippersnapper_i2c_v1_LEDBackpackConfig_brightness_tag 1 +#define wippersnapper_i2c_v1_LEDBackpackConfig_alignment_tag 2 +#define wippersnapper_i2c_v1_LEDBackpackWrite_message_tag 1 +#define wippersnapper_i2c_v1_SSD1306Config_width_tag 1 +#define wippersnapper_i2c_v1_SSD1306Config_height_tag 2 +#define wippersnapper_i2c_v1_SSD1306Config_text_size_tag 3 +#define wippersnapper_i2c_v1_SSD1306Write_message_tag 1 #define wippersnapper_i2c_v1_SensorEvent_type_tag 1 #define wippersnapper_i2c_v1_SensorEvent_value_tag 2 #define wippersnapper_i2c_v1_I2CBusScanRequest_i2c_port_number_tag 1 #define wippersnapper_i2c_v1_I2CBusScanRequest_bus_init_request_tag 2 #define wippersnapper_i2c_v1_I2CDeviceEvent_sensor_address_tag 1 #define wippersnapper_i2c_v1_I2CDeviceEvent_sensor_event_tag 2 +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_i2c_device_address_tag 1 +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_i2c_device_name_tag 2 +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_led_backpack_tag 3 +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_char_lcd_tag 4 +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_write_ssd1306_tag 5 +#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_port_number_tag 1 +#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_device_address_tag 2 +#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_device_name_tag 3 +#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_device_properties_tag 4 +#define wippersnapper_i2c_v1_I2COutputAdd_led_backpack_config_tag 1 +#define wippersnapper_i2c_v1_I2COutputAdd_char_lcd_config_tag 2 +#define wippersnapper_i2c_v1_I2COutputAdd_ssd1306_config_tag 3 #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_port_number_tag 1 #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_bus_init_req_tag 2 #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_device_address_tag 3 #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_device_name_tag 4 #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_device_properties_tag 5 -#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_port_number_tag 1 -#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_device_address_tag 2 -#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_device_name_tag 3 -#define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_i2c_device_properties_tag 4 +#define wippersnapper_i2c_v1_I2CDeviceInitRequest_is_output_device_tag 6 +#define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_output_add_tag 7 /* Struct field encoding specification for nanopb */ #define wippersnapper_i2c_v1_I2CBusInitRequest_FIELDLIST(X, a) \ @@ -281,11 +390,14 @@ X(a, STATIC, SINGULAR, INT32, i2c_port_number, 1) \ X(a, STATIC, OPTIONAL, MESSAGE, i2c_bus_init_req, 2) \ X(a, STATIC, SINGULAR, UINT32, i2c_device_address, 3) \ X(a, STATIC, SINGULAR, STRING, i2c_device_name, 4) \ -X(a, STATIC, REPEATED, MESSAGE, i2c_device_properties, 5) +X(a, STATIC, REPEATED, MESSAGE, i2c_device_properties, 5) \ +X(a, STATIC, SINGULAR, BOOL, is_output_device, 6) \ +X(a, STATIC, OPTIONAL, MESSAGE, i2c_output_add, 7) #define wippersnapper_i2c_v1_I2CDeviceInitRequest_CALLBACK NULL #define wippersnapper_i2c_v1_I2CDeviceInitRequest_DEFAULT NULL #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_bus_init_req_MSGTYPE wippersnapper_i2c_v1_I2CBusInitRequest #define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_device_properties_MSGTYPE wippersnapper_i2c_v1_I2CDeviceSensorProperties +#define wippersnapper_i2c_v1_I2CDeviceInitRequest_i2c_output_add_MSGTYPE wippersnapper_i2c_v1_I2COutputAdd #define wippersnapper_i2c_v1_I2CDeviceInitResponse_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UINT32, i2c_device_address, 2) \ @@ -333,6 +445,63 @@ X(a, STATIC, REPEATED, MESSAGE, sensor_event, 2) #define wippersnapper_i2c_v1_I2CDeviceEvent_DEFAULT NULL #define wippersnapper_i2c_v1_I2CDeviceEvent_sensor_event_MSGTYPE wippersnapper_i2c_v1_SensorEvent +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, i2c_device_address, 1) \ +X(a, STATIC, SINGULAR, STRING, i2c_device_name, 2) \ +X(a, STATIC, ONEOF, MESSAGE, (output_msg,write_led_backpack,output_msg.write_led_backpack), 3) \ +X(a, STATIC, ONEOF, MESSAGE, (output_msg,write_char_lcd,output_msg.write_char_lcd), 4) \ +X(a, STATIC, ONEOF, MESSAGE, (output_msg,write_ssd1306,output_msg.write_ssd1306), 5) +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_CALLBACK NULL +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_DEFAULT NULL +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_output_msg_write_led_backpack_MSGTYPE wippersnapper_i2c_v1_LEDBackpackWrite +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_output_msg_write_char_lcd_MSGTYPE wippersnapper_i2c_v1_CharLCDWrite +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_output_msg_write_ssd1306_MSGTYPE wippersnapper_i2c_v1_SSD1306Write + +#define wippersnapper_i2c_v1_LEDBackpackConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, INT32, brightness, 1) \ +X(a, STATIC, SINGULAR, UENUM, alignment, 2) +#define wippersnapper_i2c_v1_LEDBackpackConfig_CALLBACK NULL +#define wippersnapper_i2c_v1_LEDBackpackConfig_DEFAULT NULL + +#define wippersnapper_i2c_v1_CharLCDConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, rows, 1) \ +X(a, STATIC, SINGULAR, UINT32, columns, 2) +#define wippersnapper_i2c_v1_CharLCDConfig_CALLBACK NULL +#define wippersnapper_i2c_v1_CharLCDConfig_DEFAULT NULL + +#define wippersnapper_i2c_v1_SSD1306Config_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UINT32, width, 1) \ +X(a, STATIC, SINGULAR, UINT32, height, 2) \ +X(a, STATIC, SINGULAR, UENUM, text_size, 3) +#define wippersnapper_i2c_v1_SSD1306Config_CALLBACK NULL +#define wippersnapper_i2c_v1_SSD1306Config_DEFAULT NULL + +#define wippersnapper_i2c_v1_I2COutputAdd_FIELDLIST(X, a) \ +X(a, STATIC, ONEOF, MESSAGE, (config,led_backpack_config,config.led_backpack_config), 1) \ +X(a, STATIC, ONEOF, MESSAGE, (config,char_lcd_config,config.char_lcd_config), 2) \ +X(a, STATIC, ONEOF, MESSAGE, (config,ssd1306_config,config.ssd1306_config), 3) +#define wippersnapper_i2c_v1_I2COutputAdd_CALLBACK NULL +#define wippersnapper_i2c_v1_I2COutputAdd_DEFAULT NULL +#define wippersnapper_i2c_v1_I2COutputAdd_config_led_backpack_config_MSGTYPE wippersnapper_i2c_v1_LEDBackpackConfig +#define wippersnapper_i2c_v1_I2COutputAdd_config_char_lcd_config_MSGTYPE wippersnapper_i2c_v1_CharLCDConfig +#define wippersnapper_i2c_v1_I2COutputAdd_config_ssd1306_config_MSGTYPE wippersnapper_i2c_v1_SSD1306Config + +#define wippersnapper_i2c_v1_LEDBackpackWrite_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, message, 1) +#define wippersnapper_i2c_v1_LEDBackpackWrite_CALLBACK NULL +#define wippersnapper_i2c_v1_LEDBackpackWrite_DEFAULT NULL + +#define wippersnapper_i2c_v1_CharLCDWrite_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, message, 1) \ +X(a, STATIC, SINGULAR, BOOL, enable_backlight, 2) +#define wippersnapper_i2c_v1_CharLCDWrite_CALLBACK NULL +#define wippersnapper_i2c_v1_CharLCDWrite_DEFAULT NULL + +#define wippersnapper_i2c_v1_SSD1306Write_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, STRING, message, 1) +#define wippersnapper_i2c_v1_SSD1306Write_CALLBACK NULL +#define wippersnapper_i2c_v1_SSD1306Write_DEFAULT NULL + extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CBusInitRequest_msg; extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CBusInitResponse_msg; extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CBusSetFrequency_msg; @@ -348,6 +517,14 @@ extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CDeviceDeinitRequest_msg; extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CDeviceDeinitResponse_msg; extern const pb_msgdesc_t wippersnapper_i2c_v1_SensorEvent_msg; extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CDeviceEvent_msg; +extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CDeviceOutputWrite_msg; +extern const pb_msgdesc_t wippersnapper_i2c_v1_LEDBackpackConfig_msg; +extern const pb_msgdesc_t wippersnapper_i2c_v1_CharLCDConfig_msg; +extern const pb_msgdesc_t wippersnapper_i2c_v1_SSD1306Config_msg; +extern const pb_msgdesc_t wippersnapper_i2c_v1_I2COutputAdd_msg; +extern const pb_msgdesc_t wippersnapper_i2c_v1_LEDBackpackWrite_msg; +extern const pb_msgdesc_t wippersnapper_i2c_v1_CharLCDWrite_msg; +extern const pb_msgdesc_t wippersnapper_i2c_v1_SSD1306Write_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define wippersnapper_i2c_v1_I2CBusInitRequest_fields &wippersnapper_i2c_v1_I2CBusInitRequest_msg @@ -365,6 +542,14 @@ extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CDeviceEvent_msg; #define wippersnapper_i2c_v1_I2CDeviceDeinitResponse_fields &wippersnapper_i2c_v1_I2CDeviceDeinitResponse_msg #define wippersnapper_i2c_v1_SensorEvent_fields &wippersnapper_i2c_v1_SensorEvent_msg #define wippersnapper_i2c_v1_I2CDeviceEvent_fields &wippersnapper_i2c_v1_I2CDeviceEvent_msg +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_fields &wippersnapper_i2c_v1_I2CDeviceOutputWrite_msg +#define wippersnapper_i2c_v1_LEDBackpackConfig_fields &wippersnapper_i2c_v1_LEDBackpackConfig_msg +#define wippersnapper_i2c_v1_CharLCDConfig_fields &wippersnapper_i2c_v1_CharLCDConfig_msg +#define wippersnapper_i2c_v1_SSD1306Config_fields &wippersnapper_i2c_v1_SSD1306Config_msg +#define wippersnapper_i2c_v1_I2COutputAdd_fields &wippersnapper_i2c_v1_I2COutputAdd_msg +#define wippersnapper_i2c_v1_LEDBackpackWrite_fields &wippersnapper_i2c_v1_LEDBackpackWrite_msg +#define wippersnapper_i2c_v1_CharLCDWrite_fields &wippersnapper_i2c_v1_CharLCDWrite_msg +#define wippersnapper_i2c_v1_SSD1306Write_fields &wippersnapper_i2c_v1_SSD1306Write_msg /* Maximum encoded size of messages (where known) */ #define wippersnapper_i2c_v1_I2CBusInitRequest_size 39 @@ -374,7 +559,7 @@ extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CDeviceEvent_msg; #define wippersnapper_i2c_v1_I2CBusScanResponse_size 722 #define wippersnapper_i2c_v1_I2CDeviceSensorProperties_size 8 /* wippersnapper_i2c_v1_I2CDeviceInitRequests_size depends on runtime parameters */ -#define wippersnapper_i2c_v1_I2CDeviceInitRequest_size 466 +#define wippersnapper_i2c_v1_I2CDeviceInitRequest_size 486 #define wippersnapper_i2c_v1_I2CDeviceInitResponse_size 8 #define wippersnapper_i2c_v1_I2CDeviceUpdateRequest_size 425 #define wippersnapper_i2c_v1_I2CDeviceUpdateResponse_size 8 @@ -382,6 +567,14 @@ extern const pb_msgdesc_t wippersnapper_i2c_v1_I2CDeviceEvent_msg; #define wippersnapper_i2c_v1_I2CDeviceDeinitResponse_size 8 #define wippersnapper_i2c_v1_SensorEvent_size 7 #define wippersnapper_i2c_v1_I2CDeviceEvent_size 141 +#define wippersnapper_i2c_v1_I2CDeviceOutputWrite_size 525 +#define wippersnapper_i2c_v1_LEDBackpackConfig_size 13 +#define wippersnapper_i2c_v1_CharLCDConfig_size 12 +#define wippersnapper_i2c_v1_SSD1306Config_size 14 +#define wippersnapper_i2c_v1_I2COutputAdd_size 16 +#define wippersnapper_i2c_v1_LEDBackpackWrite_size 130 +#define wippersnapper_i2c_v1_CharLCDWrite_size 132 +#define wippersnapper_i2c_v1_SSD1306Write_size 258 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 32a121027..87af9a92e 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index 20785706d..3c9d51238 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index 916c76794..a7fb45322 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index ef9c24d61..65c3de75a 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index 3d1a1f9cb..7cfdd2901 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index f66f89c53..e3cdf3439 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index 2156a2976..7431b6661 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index 36d2f736f..063a04554 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index 14b3cc63e..ac1d37b30 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 1ab716b8f..1939d6407 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED @@ -76,6 +76,7 @@ typedef struct _wippersnapper_signal_v1_I2CRequest { wippersnapper_i2c_v1_I2CDeviceDeinitRequest req_i2c_device_deinit; wippersnapper_i2c_v1_I2CDeviceUpdateRequest req_i2c_device_update; wippersnapper_i2c_v1_I2CDeviceInitRequests req_i2c_device_init_requests; + wippersnapper_i2c_v1_I2CDeviceOutputWrite req_i2c_device_out_write; } payload; } wippersnapper_signal_v1_I2CRequest; @@ -230,6 +231,7 @@ extern "C" { #define wippersnapper_signal_v1_I2CRequest_req_i2c_device_deinit_tag 5 #define wippersnapper_signal_v1_I2CRequest_req_i2c_device_update_tag 6 #define wippersnapper_signal_v1_I2CRequest_req_i2c_device_init_requests_tag 7 +#define wippersnapper_signal_v1_I2CRequest_req_i2c_device_out_write_tag 8 #define wippersnapper_signal_v1_I2CResponse_resp_i2c_scan_tag 2 #define wippersnapper_signal_v1_I2CResponse_resp_i2c_device_init_tag 3 #define wippersnapper_signal_v1_I2CResponse_resp_i2c_device_deinit_tag 4 @@ -294,7 +296,8 @@ X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_set_freq,payload.req_i2c_set X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_init,payload.req_i2c_device_init), 4) \ X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_deinit,payload.req_i2c_device_deinit), 5) \ X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_update,payload.req_i2c_device_update), 6) \ -X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_init_requests,payload.req_i2c_device_init_requests), 7) +X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_init_requests,payload.req_i2c_device_init_requests), 7) \ +X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_out_write,payload.req_i2c_device_out_write), 8) #define wippersnapper_signal_v1_I2CRequest_CALLBACK NULL #define wippersnapper_signal_v1_I2CRequest_DEFAULT NULL #define wippersnapper_signal_v1_I2CRequest_payload_req_i2c_scan_MSGTYPE wippersnapper_i2c_v1_I2CBusScanRequest @@ -303,6 +306,7 @@ X(a, STATIC, ONEOF, MSG_W_CB, (payload,req_i2c_device_init_requests,payload #define wippersnapper_signal_v1_I2CRequest_payload_req_i2c_device_deinit_MSGTYPE wippersnapper_i2c_v1_I2CDeviceDeinitRequest #define wippersnapper_signal_v1_I2CRequest_payload_req_i2c_device_update_MSGTYPE wippersnapper_i2c_v1_I2CDeviceUpdateRequest #define wippersnapper_signal_v1_I2CRequest_payload_req_i2c_device_init_requests_MSGTYPE wippersnapper_i2c_v1_I2CDeviceInitRequests +#define wippersnapper_signal_v1_I2CRequest_payload_req_i2c_device_out_write_MSGTYPE wippersnapper_i2c_v1_I2CDeviceOutputWrite #define wippersnapper_signal_v1_I2CResponse_FIELDLIST(X, a) \ X(a, STATIC, ONEOF, MSG_W_CB, (payload,resp_i2c_scan,payload.resp_i2c_scan), 2) \ @@ -444,7 +448,7 @@ extern const pb_msgdesc_t wippersnapper_signal_v1_DisplayResponse_msg; #define wippersnapper_signal_v1_Ds18x20Request_size 39 #define wippersnapper_signal_v1_Ds18x20Response_size 26 #if defined(wippersnapper_i2c_v1_I2CDeviceInitRequests_size) -union wippersnapper_signal_v1_I2CRequest_payload_size_union {char f7[(6 + wippersnapper_i2c_v1_I2CDeviceInitRequests_size)]; char f0[469];}; +union wippersnapper_signal_v1_I2CRequest_payload_size_union {char f7[(6 + wippersnapper_i2c_v1_I2CDeviceInitRequests_size)]; char f0[528];}; #define wippersnapper_signal_v1_I2CRequest_size (0 + sizeof(union wippersnapper_signal_v1_I2CRequest_payload_size_union)) #endif #define wippersnapper_signal_v1_I2CResponse_size 725 diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index f221f6d28..2f7925a88 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index 67eb6911d..101d5bb60 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Fri Sep 5 15:04:00 2025. */ +/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From 3a989771efed4a074ab34f8bca089657f38a4a58 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 8 Sep 2025 16:21:45 -0400 Subject: [PATCH 52/76] Run debug, add splashscreen for ePD --- src/Wippersnapper.cpp | 1 + src/components/display/assets/splash.h | 1018 +++++++++++++++++ src/components/display/drivers/dispDrvBase.h | 1 + .../dispDrvThinkInkGrayscale4Eaamfgn.h | 4 +- .../register/Wippersnapper_Register.cpp | 1 + 5 files changed, 1023 insertions(+), 2 deletions(-) create mode 100644 src/components/display/assets/splash.h diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index cb9ff1898..459e43248 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2826,6 +2826,7 @@ void Wippersnapper::connect() { WS._analogIO = new Wippersnapper_AnalogIO(5, 3.3); // Configure hardware + WS.pinCfgCompleted = true; while (!WS.pinCfgCompleted) { WS_DEBUG_PRINTLN( "Polling for message containing hardware configuration..."); diff --git a/src/components/display/assets/splash.h b/src/components/display/assets/splash.h new file mode 100644 index 000000000..c0eaec4fe --- /dev/null +++ b/src/components/display/assets/splash.h @@ -0,0 +1,1018 @@ +#ifndef _SPLASH_H_ +#define _SPLASH_H_ +#include + +// 'adafruit_wippersnapper_logo', 240x135px +static const unsigned char tft_bitmap_ws_logo_240135 [] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf7, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x80, 0xf3, 0xff, 0xff, 0xfb, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0x00, 0xf1, 0xff, 0xff, 0xb3, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfc, 0xc1, 0x7f, 0xff, 0x00, 0xf1, 0xff, 0xfd, 0x32, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x00, 0x7f, 0xff, 0x00, 0xf1, 0xff, 0xfd, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x00, 0x7f, + 0xfe, 0x00, 0xe0, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xfe, 0x00, + 0x60, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xfc, 0x00, 0x60, 0xff, + 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, 0xfc, 0x30, 0x60, 0x7f, 0xf0, 0x00, + 0x1e, 0x00, 0xf8, 0x00, 0x03, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x1f, 0xfc, 0x70, 0x00, 0x7f, 0xf0, 0x00, 0x1e, 0x00, + 0x70, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xfc, 0xc0, 0x00, 0x3f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, + 0x00, 0x1f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xe0, 0x00, 0x0f, 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, + 0x00, 0x0f, 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, + 0xf8, 0xc0, 0x00, 0x1f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf0, 0x60, + 0x00, 0x1f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x1f, + 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xe0, 0x00, + 0x1f, 0xff, 0xf0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x01, 0xfc, 0x01, 0xc7, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x1e, 0x00, + 0x70, 0x01, 0xc0, 0x03, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, + 0xe0, 0x03, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x00, 0x7c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, + 0x00, 0x1f, 0x00, 0x1c, 0x00, 0x00, 0x3c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, + 0x00, 0x07, 0xc0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x00, 0x1f, + 0x00, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, + 0x80, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x00, 0x1f, 0x00, 0x18, + 0x00, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x00, 0x1e, 0x00, 0x10, 0x00, 0x00, + 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xc0, 0x03, 0x00, 0x0e, 0x00, 0x10, 0x03, 0x80, 0x0c, 0x00, + 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x03, 0x80, 0x0c, 0x00, 0x0f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, + 0x70, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0c, 0x00, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x00, 0x00, + 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0xf0, + 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x61, 0xff, + 0xff, 0x0e, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x01, 0xf0, 0x03, 0xff, + 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfe, + 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0xff, 0x00, 0x00, 0x07, 0xf0, 0x01, 0xff, 0xfc, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, + 0x7e, 0x00, 0x70, 0x00, 0x1f, 0xff, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xf0, 0x0f, 0xff, 0x00, 0x00, 0x3e, 0x00, + 0x70, 0x01, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf8, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, + 0xff, 0xff, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf0, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, + 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, + 0x00, 0x3f, 0x80, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x00, 0x1f, + 0xff, 0xfc, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xfe, + 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x01, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0x90, 0x1f, 0x00, 0xf8, 0x03, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xff, 0x80, 0x00, + 0x7c, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf8, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0x00, 0x04, 0x07, 0xc0, 0x60, 0x00, 0xff, 0xc0, 0x01, 0x81, 0xe0, 0x7c, 0x00, + 0xf0, 0x00, 0x78, 0x00, 0x3c, 0x00, 0x0c, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xfc, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x7f, 0x80, 0x01, 0x00, 0xe0, 0x7c, 0x00, 0xf0, 0x00, + 0x38, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0x80, 0x03, 0x00, 0xe0, 0x78, 0x00, 0xf0, 0x00, 0x38, 0x00, + 0x1c, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xff, + 0xff, 0xf0, 0x00, 0x3f, 0x00, 0x03, 0x00, 0x60, 0x78, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x0c, 0x00, + 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xf0, 0x1f, 0xf8, + 0x00, 0x3f, 0x00, 0x03, 0x00, 0x60, 0x70, 0x00, 0xf0, 0x00, 0x10, 0x00, 0x08, 0x00, 0x1c, 0x00, + 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x7f, 0x80, 0x01, 0xfe, 0x00, 0x3f, + 0x03, 0xfb, 0x00, 0x60, 0x70, 0x20, 0xe0, 0x30, 0x10, 0x18, 0x08, 0x0f, 0xf8, 0x1c, 0x07, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xfc, 0x00, 0x00, 0x7f, 0x00, 0x3e, 0x00, 0x7f, + 0x00, 0x00, 0xe0, 0x60, 0xe0, 0x38, 0x10, 0x18, 0x08, 0x00, 0x78, 0x1c, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x01, 0xf8, 0x00, 0x00, 0x3f, 0x80, 0x7e, 0x00, 0x0f, 0x00, 0x00, + 0xe0, 0x60, 0xe0, 0x30, 0x30, 0x18, 0x18, 0x00, 0x78, 0x1c, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x00, 0x00, 0x0f, 0xf8, 0xfe, 0x00, 0x06, 0x00, 0x00, 0xe0, 0x60, + 0xe0, 0x60, 0x30, 0x30, 0x18, 0x00, 0x78, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0xc0, 0xe0, 0xe0, 0x00, + 0x30, 0x00, 0x18, 0x00, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x02, 0x00, 0x00, 0xc0, 0xe0, 0xc0, 0x00, 0x60, 0x00, + 0x30, 0x00, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x01, 0xff, 0xff, 0xf0, 0x06, 0x04, 0x00, 0x80, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x70, 0x1f, + 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xfe, 0xfc, 0x06, 0x04, 0x00, 0x80, 0x00, 0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x1f, 0xf0, 0x00, + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x30, 0x18, 0x00, 0x7f, 0xfc, + 0x00, 0x04, 0x0e, 0x00, 0x80, 0x00, 0xc0, 0x07, 0xe0, 0x03, 0xf0, 0x00, 0x70, 0x20, 0x3f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x04, + 0x0e, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xe0, 0x7f, 0xf0, 0x00, 0x70, 0x30, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x0c, 0x0e, 0x01, + 0x00, 0x00, 0xc0, 0xff, 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xfc, 0x00, 0x7f, 0xfc, 0x00, 0x1c, 0x0f, 0x00, 0x03, 0xc0, + 0x80, 0xff, 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0x00, 0xfc, 0x7e, 0x00, 0x7f, 0xfc, 0x00, 0x3c, 0x0f, 0x00, 0x07, 0xc0, 0x80, 0xff, + 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x01, 0xf0, 0x0f, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, + 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff +}; + +// 'adafruit_wippersnapper_logo', 240x240px +static const unsigned char tft_bitmap_ws_logo_240240 [] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xc0, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, + 0xff, 0x80, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0x00, + 0xf1, 0xff, 0xff, 0xb3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x89, 0xff, 0xff, 0x00, 0xf1, 0xff, + 0xff, 0x12, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0x00, 0xf0, 0xff, 0xfc, 0x00, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x7f, 0xfe, 0x00, 0xe0, 0xff, 0xfc, 0x00, 0x1f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xfe, 0x00, 0x60, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf0, 0x00, 0x3f, 0xfe, 0x00, 0x60, 0x7f, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, + 0x00, 0x1f, 0xfc, 0x30, 0x60, 0x7f, 0xf0, 0x00, 0x1f, 0x00, 0xf8, 0x00, 0x07, 0xff, 0xc0, 0x00, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, + 0xfc, 0x70, 0x00, 0x7f, 0xf0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x07, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xfc, 0xc0, + 0x00, 0x3f, 0xf0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x01, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf8, 0x80, 0x00, 0x3f, + 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, + 0x0e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf8, 0xc0, 0x00, 0x1f, 0xe0, 0x00, 0x0e, 0x00, + 0x70, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf0, 0x60, 0x00, 0x1f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, + 0x00, 0x07, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xe0, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, + 0x80, 0x00, 0x00, 0x3f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, + 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, 0x80, 0x00, + 0x00, 0x3f, 0x80, 0x01, 0xfc, 0x01, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, + 0xe0, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xc0, 0x03, 0x80, 0x1e, 0x00, 0x1f, + 0x00, 0x00, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xe0, 0x00, + 0x00, 0x0f, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1f, 0x00, 0x1e, 0x00, 0x00, + 0x7c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, + 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1f, 0x00, 0x1c, 0x00, 0x00, 0x3c, 0x00, + 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x07, 0xc0, 0x00, + 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1f, 0x00, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x07, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x1e, 0x00, + 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1f, 0x00, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, + 0xe0, 0x03, 0x80, 0x1e, 0x00, 0x10, 0x01, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xc0, 0x03, + 0x80, 0x0e, 0x00, 0x10, 0x03, 0x80, 0x0c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x80, 0x00, + 0x00, 0x30, 0x03, 0x80, 0x0c, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x0c, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, + 0x70, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x61, 0xff, 0xff, 0x0e, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, + 0x00, 0x3f, 0x80, 0x00, 0x01, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0xff, + 0x80, 0x00, 0x07, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x1f, 0xff, 0x80, 0x00, + 0xff, 0xf0, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, + 0xff, 0xe0, 0x0f, 0xff, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xf0, + 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x07, 0xfc, 0x00, + 0x00, 0x7f, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xf8, 0x00, 0x00, + 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x0f, + 0xf0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x03, 0xf8, 0x00, + 0x0e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xfc, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x0e, 0x00, + 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xfe, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x1e, 0x00, 0xf8, 0x03, + 0xff, 0xff, 0x80, 0x1f, 0xff, 0xff, 0x80, 0x00, 0x3c, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xf0, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x04, 0x07, 0xc0, 0x60, + 0x00, 0xff, 0xc0, 0x01, 0x81, 0xe0, 0x3c, 0x00, 0xf0, 0x00, 0x78, 0x00, 0x3c, 0x00, 0x0c, 0x00, + 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x7f, + 0x80, 0x01, 0x00, 0xe0, 0x7c, 0x00, 0xf0, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x0f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0x80, 0x03, + 0x00, 0xe0, 0x78, 0x00, 0xf0, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0x00, 0x03, 0x00, 0x60, + 0x78, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xf0, 0x1f, 0xf8, 0x00, 0x3f, 0x00, 0x03, 0x00, 0x60, 0x70, 0x00, + 0xf0, 0x00, 0x18, 0x00, 0x08, 0x00, 0x18, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xf8, 0x00, 0x7f, 0x80, 0x01, 0xfe, 0x00, 0x3e, 0x03, 0xfb, 0x00, 0x60, 0x70, 0x20, 0xe0, 0x30, + 0x10, 0x18, 0x08, 0x0f, 0xf8, 0x1c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0xfc, 0x00, 0x00, 0x7f, 0x00, 0x3e, 0x00, 0x7f, 0x00, 0x00, 0x70, 0x60, 0xe0, 0x30, 0x10, 0x18, + 0x08, 0x00, 0x78, 0x1c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x03, 0xf8, 0x00, + 0x00, 0x1f, 0x80, 0x7e, 0x00, 0x0e, 0x00, 0x00, 0xe0, 0x60, 0xe0, 0x30, 0x30, 0x38, 0x18, 0x00, + 0x78, 0x1c, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x00, 0x00, 0x0f, + 0xf8, 0xfe, 0x00, 0x06, 0x00, 0x00, 0xe0, 0x60, 0xe0, 0x30, 0x30, 0x30, 0x18, 0x00, 0x78, 0x00, + 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, + 0x00, 0x06, 0x00, 0x00, 0xc0, 0xe0, 0xe0, 0x00, 0x30, 0x00, 0x18, 0x00, 0x78, 0x00, 0x0f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x06, + 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x06, 0x04, 0x00, + 0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x1f, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x06, 0x04, 0x00, 0x80, 0x00, + 0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x1f, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0x00, 0x30, 0x18, 0x00, 0x7f, 0xfc, 0x00, 0x04, 0x06, 0x01, 0x80, 0x00, 0xc0, 0x07, + 0xe0, 0x03, 0xf0, 0x00, 0x70, 0x20, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x04, 0x0e, 0x01, 0x00, 0x00, 0x40, 0xff, 0xe0, 0x7f, + 0xf0, 0x00, 0x70, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, + 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x0c, 0x0e, 0x01, 0x00, 0x00, 0x40, 0xff, 0xe0, 0x7f, 0xe0, 0x00, + 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xfc, 0x00, + 0x7f, 0xfc, 0x00, 0x1c, 0x0f, 0x00, 0x03, 0xc0, 0x00, 0xff, 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0xfc, 0x7e, 0x00, 0x7f, 0xfc, + 0x00, 0x3c, 0x0f, 0x00, 0x07, 0xc0, 0x00, 0xff, 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, 0x3f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf0, 0x0f, 0x80, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, + 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, + 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +// 'adafruit_wippersnapper_logo', ePD Magtag, 296x128px +static const unsigned char epd_bitmap_ws_logo_296128 [] = { + // 'adafruit_wippersnapper_logo, 296x128px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x18, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x03, 0xfe, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x03, 0xfc, 0x0e, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x73, 0x00, 0x00, 0x07, 0xfc, 0x0f, 0x00, + 0x00, 0x06, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x20, + 0x00, 0x07, 0xfc, 0x0f, 0x00, 0x00, 0x27, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xff, 0x60, 0x00, 0x07, 0xfe, 0x0f, 0x00, 0x00, 0x37, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xff, 0xe0, 0x00, 0x0f, 0xfe, 0x1f, 0x80, 0x00, + 0x3f, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0x00, + 0x0f, 0xfe, 0x1f, 0x80, 0x00, 0x3f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0x1f, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x00, 0x1f, 0xff, 0x3f, 0xc0, 0x00, 0x7f, + 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x1f, + 0x1f, 0x3f, 0xc0, 0x00, 0xff, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0xff, 0xf8, 0x00, 0x1c, 0x3f, 0xbf, 0xc0, 0x00, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, + 0xff, 0x00, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x38, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, + 0xe1, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x39, 0xff, + 0xff, 0xe0, 0x01, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0xff, 0xfc, 0x00, 0x39, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0xff, + 0xf0, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x79, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xe1, + 0xff, 0xe1, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x79, 0xff, 0xff, + 0xf0, 0x01, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfc, 0x00, 0x7c, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfc, + 0x3f, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0xfe, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xe0, 0xff, + 0xc1, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0xfe, 0xff, 0xff, 0xf8, + 0x03, 0xff, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x07, + 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, + 0x00, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x3f, + 0xff, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xf0, 0x0f, 0xff, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x01, 0xff, 0xff, 0xff, 0xfc, 0x03, 0xff, 0xff, 0xe1, 0xff, 0xe1, + 0xff, 0xf0, 0x7f, 0xfe, 0x3f, 0xfe, 0x0f, 0xff, 0xc0, 0x7f, 0xff, 0xf8, 0x0f, 0xff, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x01, 0xff, 0xff, 0xff, 0xfc, 0x03, + 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc0, 0xff, 0xff, + 0xfc, 0x0f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x01, + 0xff, 0xff, 0xff, 0xfc, 0x07, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, + 0x07, 0xff, 0xc1, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, + 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc3, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xff, + 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc3, 0xff, 0xff, 0xff, + 0x0f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x8f, 0xff, + 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, 0x07, + 0xff, 0xc7, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0x81, 0xff, 0xe1, 0xff, 0xf0, + 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc7, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x81, 0xff, 0xe1, 0xff, 0xf0, 0x7f, 0xfe, 0x3f, 0xfe, 0x0f, 0xff, 0xc7, 0xff, 0x8f, 0xff, 0x8f, + 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0xe1, 0xff, 0xf9, 0xff, 0xfe, 0x3f, 0xff, 0x1f, 0xff, + 0xcf, 0xff, 0x87, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0xe1, 0xff, 0xff, 0xff, + 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xcf, 0xff, 0x87, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, + 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0x8f, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0x8f, + 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfc, + 0x3f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x01, 0xff, + 0xe1, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xfe, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0x0f, 0xff, + 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, + 0xfb, 0xff, 0xf0, 0x7f, 0xfe, 0xff, 0xff, 0xfe, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xf0, 0x3f, + 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xff, 0xff, 0xf1, 0xf8, 0x00, 0x00, 0xfc, 0x7f, 0xff, 0xfc, 0x01, 0xff, 0xe1, + 0xff, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xf8, 0x0f, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xff, 0xfc, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0x80, + 0x00, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfe, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, + 0xff, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0x01, 0xff, 0xe1, 0xff, + 0xf0, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x80, 0x01, 0xff, 0xfc, 0x00, 0x0f, 0xff, + 0xff, 0x81, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, + 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xfe, 0x00, 0x1f, + 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xfe, 0x00, + 0x00, 0x07, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, + 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0x07, 0xff, 0xff, 0xff, 0xff, 0x00, 0x7f, 0xff, + 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0x8f, + 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, + 0x01, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0xff, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x00, + 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xe0, + 0xff, 0xe0, 0xff, 0xf0, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x07, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x03, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfe, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, + 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x02, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x9f, 0xff, 0xff, 0xcf, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0x1f, + 0xe1, 0xff, 0x07, 0xff, 0x83, 0xff, 0xfc, 0x1f, 0xff, 0xe0, 0xff, 0xff, 0xdf, 0xff, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8e, 0x00, 0x03, 0x8f, 0xff, + 0xf8, 0x00, 0xff, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0xff, 0x81, 0xff, 0xfe, 0x0f, 0xff, 0xf0, 0xff, + 0xff, 0x8f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, + 0x80, 0x00, 0x00, 0x0f, 0xff, 0xfc, 0x01, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x07, 0xff, 0xc1, 0xff, + 0xff, 0x1f, 0xff, 0xf8, 0xff, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, 0x01, 0xff, 0xff, 0x3f, 0xf0, + 0xfe, 0x0f, 0xff, 0xc3, 0xff, 0xff, 0x9f, 0xff, 0xf8, 0xff, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, + 0x03, 0xff, 0xff, 0x3f, 0xf9, 0xfe, 0x0f, 0xff, 0xc3, 0xff, 0xff, 0x9f, 0xff, 0xfc, 0xff, 0xff, + 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfc, 0x00, + 0x3f, 0xe0, 0x01, 0xff, 0xff, 0x03, 0xff, 0xfe, 0x3f, 0xf9, 0xfe, 0x1f, 0xff, 0xc3, 0xff, 0xff, + 0x9f, 0xff, 0xfc, 0xff, 0xff, 0x9f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0xf0, 0x03, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0x03, 0xfc, 0x02, 0x3f, 0xfd, 0xfe, + 0x1f, 0xdf, 0xc3, 0xfc, 0xff, 0x9f, 0xc7, 0xfc, 0xfe, 0x00, 0x1f, 0xe3, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0x80, 0x3f, 0xfe, 0x07, + 0xff, 0x00, 0x3f, 0xfd, 0xfe, 0x3f, 0x9f, 0xc3, 0xfc, 0x7f, 0x9f, 0xc3, 0xfd, 0xfe, 0x00, 0x1f, + 0xe3, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xc0, 0x3f, 0xff, + 0xff, 0xe0, 0x1f, 0xfe, 0x07, 0xff, 0xf0, 0x7f, 0xff, 0xfc, 0x3f, 0x9f, 0xc3, 0xf8, 0x7f, 0xbf, + 0xc7, 0xf9, 0xff, 0xfc, 0x1f, 0xe3, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xf9, 0x00, 0xff, 0xff, 0xff, 0xf8, 0x04, 0xfc, 0x07, 0xff, 0xfc, 0x7f, 0xff, 0xfc, 0x3f, + 0x9f, 0xc7, 0xf8, 0xff, 0x3f, 0xc7, 0xf9, 0xff, 0xfc, 0x1f, 0xc3, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x30, 0x07, 0xff, + 0xfc, 0x7f, 0xff, 0xfc, 0x7f, 0x1f, 0xc7, 0xf8, 0xff, 0x3f, 0xc7, 0xf9, 0xff, 0xfc, 0x1f, 0xff, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, + 0xfe, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x7f, 0xff, 0xfc, 0x7f, 0x1f, 0xc7, 0xff, 0xff, 0x3f, 0xff, + 0xf9, 0xff, 0xfc, 0x3f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0xff, 0xfe, 0x7f, 0xff, 0xfc, 0x7f, 0x1f, + 0xc7, 0xff, 0xfe, 0x3f, 0xff, 0xf1, 0xff, 0xf8, 0x3f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0xff, 0xfe, + 0x7f, 0x7f, 0xfc, 0xff, 0x3f, 0xc7, 0xff, 0xfe, 0x3f, 0xff, 0xf3, 0xff, 0xf8, 0x3f, 0xff, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, + 0xc0, 0x00, 0x00, 0x0f, 0xfe, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xcf, 0xff, 0xfc, 0x7f, 0xff, 0xe3, + 0xfc, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xfe, 0xff, 0x3f, 0xf9, 0xff, 0xff, 0xcf, + 0xff, 0xf8, 0x7f, 0xff, 0xc3, 0xfc, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x3f, 0xe7, 0xff, 0xe0, 0x00, 0x0f, 0xff, 0xfc, 0xff, + 0x3f, 0xf9, 0xff, 0xff, 0xcf, 0xff, 0xe0, 0x7f, 0xff, 0x03, 0xff, 0xfe, 0x3f, 0x9f, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x1f, 0xc3, 0xff, 0xf0, + 0x00, 0x0f, 0xff, 0xfc, 0xff, 0x1f, 0xf9, 0xff, 0xff, 0xcf, 0xf0, 0x00, 0x7f, 0x80, 0x03, 0xff, + 0xfc, 0x7f, 0x9f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xfe, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xf8, 0xfe, 0x1f, 0xfb, 0xff, 0xff, 0xcf, 0xf0, + 0x00, 0x7f, 0x00, 0x07, 0xff, 0xfc, 0x7f, 0x9f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xf9, 0xfe, 0x1f, + 0xfb, 0xff, 0xff, 0xcf, 0xe0, 0x00, 0xff, 0x00, 0x07, 0xff, 0xfc, 0x7f, 0x9f, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x01, 0xff, 0xf0, 0x00, + 0x1f, 0xff, 0xf1, 0xfe, 0x0f, 0xf7, 0xf8, 0x1f, 0xdf, 0xe0, 0x00, 0xff, 0x00, 0x07, 0xff, 0xfc, + 0x7f, 0x9f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, + 0x02, 0x00, 0xff, 0xe0, 0x00, 0x0f, 0xff, 0xc1, 0xfe, 0x0f, 0xf7, 0xf8, 0x1f, 0xff, 0xe0, 0x00, + 0xff, 0x00, 0x07, 0xff, 0xfc, 0x7f, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0xf0, 0x3f, 0xe0, 0x7f, 0xc0, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x7f, 0xf0, 0x07, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +#endif // SPLASH_H \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index d74c2d733..939886511 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -17,6 +17,7 @@ #include "Adafruit_ThinkInk.h" #include "Wippersnapper.h" +#include "../assets/splash.h" /*! @brief Abstract base class for display drivers. diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index 426307d1b..8038ce120 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -72,10 +72,10 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { _display->setTextWrap(false); _height = _display->height(); _width = _display->width(); - // Clear the display buffer _display->clearBuffer(); + // Show splash screen + _display->drawBitmap(0, 0, epd_bitmap_ws_logo_296128, 296, 128, EPD_BLACK); _display->display(); - return true; } diff --git a/src/components/register/Wippersnapper_Register.cpp b/src/components/register/Wippersnapper_Register.cpp index ee27c5e82..3d9b4b401 100644 --- a/src/components/register/Wippersnapper_Register.cpp +++ b/src/components/register/Wippersnapper_Register.cpp @@ -77,6 +77,7 @@ bool Wippersnapper::encodePubRegistrationReq() { /****************************************************************************/ void Wippersnapper::pollRegistrationResp() { // Blocking loop, WDT reset upon failure. + WS._boardStatus = WS_BOARD_DEF_OK; while (WS._boardStatus != WS_BOARD_DEF_OK) { WS_DEBUG_PRINT("Polling for registration message response..."); WS_DEBUG_PRINTLN(WS._boardStatus); From 564959bbc1a6a66d9fa83370958b7309971e4626 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 9 Sep 2025 12:27:36 -0400 Subject: [PATCH 53/76] Briefly show splash, add more epd modes, add feed for wdt so it doesnt miss ping and dc --- src/components/display/drivers/dispDrvBase.h | 9 +++++++++ .../drivers/dispDrvThinkInkGrayscale4Eaamfgn.h | 12 +++++++++++- src/components/display/hardware.cpp | 13 +++++++++++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index 939886511..1830257b0 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -125,6 +125,15 @@ class dispDrvBase { */ virtual void setTextSize(uint8_t s) { _text_sz = s; } + + /*! + @brief Displays a splash screen on the display. + @note This method can be overridden by derived classes to provide + specific functionality. + */ + virtual void showSplash() { // No-op for base class + } + protected: int16_t _pin_dc; ///< Data/Command pin int16_t _pin_rst; ///< Reset pin diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index 8038ce120..e2da13a8c 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -73,10 +73,20 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { _height = _display->height(); _width = _display->width(); _display->clearBuffer(); + return true; + } + + virtual void showSplash() override { + if (_display == nullptr) + return; + // Show splash screen _display->drawBitmap(0, 0, epd_bitmap_ws_logo_296128, 296, 128, EPD_BLACK); _display->display(); - return true; + delay(1000); + _display->clearBuffer(); + _display->fillScreen(EPD_WHITE); + _display->display(); } /*! diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 798932f99..686b99ce3 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -240,7 +240,13 @@ bool DisplayHardware::beginEPD( thinkinkmode_t epd_mode = THINKINK_MONO; if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_GRAYSCALE4) { epd_mode = THINKINK_GRAYSCALE4; - WS_DEBUG_PRINTLN("[display] EPD mode: GRAYSCALE4"); + } else if (config->mode == wippersnapper_display_v1_EPDMode_EPD_MODE_MONO) { + epd_mode = THINKINK_MONO; + } else { + WS_DEBUG_PRINTLN("[display] ERROR: Unsupported EPD mode!"); + delete _drvDisp; + _drvDisp = nullptr; + return false; } if (!_drvDisp->begin(epd_mode)) { @@ -250,6 +256,10 @@ bool DisplayHardware::beginEPD( return false; } + WS.feedWDT(); + _drvDisp->showSplash(); + WS.feedWDT(); + WS_DEBUG_PRINTLN("[display] Successfully initialized epd display!"); return true; } @@ -328,7 +338,6 @@ bool DisplayHardware::beginTft( _drvDisp->setHeight(config->height); _drvDisp->setRotation(config->rotation); _drvDisp->begin(); - _drvDisp->setTextSize(text_sz); return true; } From bf1e68c1bc2d1f41cba040abbf86343d534fb83e Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 10 Sep 2025 09:41:20 -0400 Subject: [PATCH 54/76] Update PBs --- src/components/display/controller.cpp | 6 +++ src/components/display/drivers/dispDrvBase.h | 4 ++ .../dispDrvThinkInkGrayscale4Eaamfgn.h | 37 +++++++++++++++++-- src/components/display/hardware.cpp | 14 +++++-- src/components/display/hardware.h | 3 ++ .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 4 +- src/wippersnapper/display/v1/display.pb.h | 27 +++++++------- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 10 ++--- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 25 files changed, 94 insertions(+), 45 deletions(-) diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 709ef8a4f..e51e04f7d 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -69,6 +69,12 @@ bool DisplayController::Handle_Display_AddOrReplace( return false; } + WS.feedWDT(); + display->showSplash(); + WS.feedWDT(); + display->drawStatusBar(); + WS.feedWDT(); + _hw_instances.push_back(display); // Store the display instance WS_DEBUG_PRINTLN("[display] Display added or replaced successfully!"); return true; diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index 1830257b0..babd15e05 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -134,6 +134,10 @@ class dispDrvBase { virtual void showSplash() { // No-op for base class } + virtual void drawStatusBar() { + // No-op for base class + } + protected: int16_t _pin_dc; ///< Data/Command pin int16_t _pin_rst; ///< Reset pin diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index e2da13a8c..cc95d1101 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -76,16 +76,45 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { return true; } + /*! + @brief Displays a splash screen + */ virtual void showSplash() override { - if (_display == nullptr) + if (! _display) return; - - // Show splash screen _display->drawBitmap(0, 0, epd_bitmap_ws_logo_296128, 296, 128, EPD_BLACK); _display->display(); - delay(1000); + delay(50); + } + + /*! + @brief Draws a status bar at the top of the display. + */ + virtual void drawStatusBar() override { + if (!_display) + return; _display->clearBuffer(); _display->fillScreen(EPD_WHITE); + + int barHeight = 15; + int borderWidth = 1; + // Black rect outline + _display->fillRect(0, 0, _width, barHeight, EPD_BLACK); + // White rect inside for icons/text + _display->fillRect(borderWidth, borderWidth, + _width - (2 * borderWidth), + barHeight - (2 * borderWidth), + EPD_WHITE); + + // Vertically center text in the bar + _display->setTextSize(1); // Text size 1 = 8 pixels tall + int textHeight = 8; + int usableHeight = barHeight - (2 * borderWidth); // 13px usable + int textY = borderWidth + (usableHeight - textHeight) / 2; // = 1 + (13-8)/2 = 3 + // Draw status text + _display->setTextColor(EPD_BLACK); + _display->setCursor(5, textY); + _display->print("[IO] OK|[WiFi] OK|[Bat] 100%"); _display->display(); } diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 686b99ce3..bbfe418e1 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -256,13 +256,21 @@ bool DisplayHardware::beginEPD( return false; } - WS.feedWDT(); - _drvDisp->showSplash(); - WS.feedWDT(); WS_DEBUG_PRINTLN("[display] Successfully initialized epd display!"); return true; } +void DisplayHardware::showSplash() { + if (!_drvDisp) + return; + _drvDisp->showSplash(); +} + +void DisplayHardware::drawStatusBar() { + _drvDisp->drawStatusBar(); +} + + /*! @brief Removes a suffix from the hardware instance name, if it exists. @param suffix diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 9446f1467..b20075355 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -44,6 +44,9 @@ class DisplayHardware { bool beginTft(wippersnapper_display_v1_TftConfig *config, wippersnapper_display_v1_TftSpiConfig *spi_config); + + void showSplash(); + void drawStatusBar(); // // API for Adafruit_GFX that abstracts hardware functionality // NOTE: These methods are meant to be implemented within dispDrvBase and diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index 8d8cb3aea..503fdf674 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index d09c6efb8..c1f79b6b0 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 39fe9aca8..2cd13f48a 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -30,7 +30,7 @@ PB_BIND(wippersnapper_display_v1_DisplayRemove, wippersnapper_display_v1_Display PB_BIND(wippersnapper_display_v1_DisplayWrite, wippersnapper_display_v1_DisplayWrite, 2) -PB_BIND(wippersnapper_display_v1_DisplayAddedorReplaced, wippersnapper_display_v1_DisplayAddedorReplaced, AUTO) +PB_BIND(wippersnapper_display_v1_DisplayAddedOrReplaced, wippersnapper_display_v1_DisplayAddedOrReplaced, AUTO) PB_BIND(wippersnapper_display_v1_DisplayRemoved, wippersnapper_display_v1_DisplayRemoved, AUTO) diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index 1c31c7661..68571d7d8 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,11 +1,10 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #include #include "nanopb/nanopb.pb.h" -#include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 #error Regenerate this file with the current version of nanopb generator. @@ -26,10 +25,10 @@ typedef enum _wippersnapper_display_v1_EPDMode { } wippersnapper_display_v1_EPDMode; /* Struct definitions */ -typedef struct _wippersnapper_display_v1_DisplayAddedorReplaced { +typedef struct _wippersnapper_display_v1_DisplayAddedOrReplaced { char name[64]; bool did_add; -} wippersnapper_display_v1_DisplayAddedorReplaced; +} wippersnapper_display_v1_DisplayAddedOrReplaced; typedef struct _wippersnapper_display_v1_DisplayRemove { char name[64]; @@ -121,7 +120,7 @@ extern "C" { #define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} #define wippersnapper_display_v1_DisplayRemove_init_default {""} #define wippersnapper_display_v1_DisplayWrite_init_default {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_default}} -#define wippersnapper_display_v1_DisplayAddedorReplaced_init_default {"", 0} +#define wippersnapper_display_v1_DisplayAddedOrReplaced_init_default {"", 0} #define wippersnapper_display_v1_DisplayRemoved_init_default {"", 0} #define wippersnapper_display_v1_EpdSpiConfig_init_zero {0, "", "", "", "", ""} #define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN} @@ -131,12 +130,12 @@ extern "C" { #define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} #define wippersnapper_display_v1_DisplayRemove_init_zero {""} #define wippersnapper_display_v1_DisplayWrite_init_zero {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_zero}} -#define wippersnapper_display_v1_DisplayAddedorReplaced_init_zero {"", 0} +#define wippersnapper_display_v1_DisplayAddedOrReplaced_init_zero {"", 0} #define wippersnapper_display_v1_DisplayRemoved_init_zero {"", 0} /* Field tags (for use in manual encoding/decoding) */ -#define wippersnapper_display_v1_DisplayAddedorReplaced_name_tag 1 -#define wippersnapper_display_v1_DisplayAddedorReplaced_did_add_tag 2 +#define wippersnapper_display_v1_DisplayAddedOrReplaced_name_tag 1 +#define wippersnapper_display_v1_DisplayAddedOrReplaced_did_add_tag 2 #define wippersnapper_display_v1_DisplayRemove_name_tag 1 #define wippersnapper_display_v1_DisplayRemoved_name_tag 1 #define wippersnapper_display_v1_DisplayRemoved_did_remove_tag 2 @@ -234,11 +233,11 @@ X(a, STATIC, ONEOF, MESSAGE, (options,epd_options,options.epd_options), #define wippersnapper_display_v1_DisplayWrite_DEFAULT NULL #define wippersnapper_display_v1_DisplayWrite_options_epd_options_MSGTYPE wippersnapper_display_v1_EPDWriteOptions -#define wippersnapper_display_v1_DisplayAddedorReplaced_FIELDLIST(X, a) \ +#define wippersnapper_display_v1_DisplayAddedOrReplaced_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, name, 1) \ X(a, STATIC, SINGULAR, BOOL, did_add, 2) -#define wippersnapper_display_v1_DisplayAddedorReplaced_CALLBACK NULL -#define wippersnapper_display_v1_DisplayAddedorReplaced_DEFAULT NULL +#define wippersnapper_display_v1_DisplayAddedOrReplaced_CALLBACK NULL +#define wippersnapper_display_v1_DisplayAddedOrReplaced_DEFAULT NULL #define wippersnapper_display_v1_DisplayRemoved_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, name, 1) \ @@ -254,7 +253,7 @@ extern const pb_msgdesc_t wippersnapper_display_v1_TftConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayAddOrReplace_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemove_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayWrite_msg; -extern const pb_msgdesc_t wippersnapper_display_v1_DisplayAddedorReplaced_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_DisplayAddedOrReplaced_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ @@ -266,7 +265,7 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; #define wippersnapper_display_v1_DisplayAddOrReplace_fields &wippersnapper_display_v1_DisplayAddOrReplace_msg #define wippersnapper_display_v1_DisplayRemove_fields &wippersnapper_display_v1_DisplayRemove_msg #define wippersnapper_display_v1_DisplayWrite_fields &wippersnapper_display_v1_DisplayWrite_msg -#define wippersnapper_display_v1_DisplayAddedorReplaced_fields &wippersnapper_display_v1_DisplayAddedorReplaced_msg +#define wippersnapper_display_v1_DisplayAddedOrReplaced_fields &wippersnapper_display_v1_DisplayAddedOrReplaced_msg #define wippersnapper_display_v1_DisplayRemoved_fields &wippersnapper_display_v1_DisplayRemoved_msg /* Maximum encoded size of messages (where known) */ @@ -278,7 +277,7 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; #define wippersnapper_display_v1_DisplayAddOrReplace_size 157 #define wippersnapper_display_v1_DisplayRemove_size 65 #define wippersnapper_display_v1_DisplayWrite_size 1104 -#define wippersnapper_display_v1_DisplayAddedorReplaced_size 67 +#define wippersnapper_display_v1_DisplayAddedOrReplaced_size 67 #define wippersnapper_display_v1_DisplayRemoved_size 67 #ifdef __cplusplus diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index 2b844940b..b01507408 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index 84a16a5de..34bbd4dc3 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index 9a2cd926d..359d37d3d 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 0afda161c..6bc1db36c 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 87af9a92e..4de40d222 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index 3c9d51238..d07dc0df7 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index a7fb45322..083400a2e 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index 65c3de75a..e8e278326 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index 7cfdd2901..365c961fd 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index e3cdf3439..b117989ec 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index 7431b6661..a09513361 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index 063a04554..cd6b7fc66 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index ac1d37b30..a9bd94a43 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 1939d6407..0838dae8b 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED @@ -43,7 +43,7 @@ typedef struct _wippersnapper_signal_v1_DisplayResponse { pb_callback_t cb_payload; pb_size_t which_payload; union { - wippersnapper_display_v1_DisplayAddedorReplaced display_added; + wippersnapper_display_v1_DisplayAddedOrReplaced display_added; wippersnapper_display_v1_DisplayRemoved display_removed; } payload; } wippersnapper_signal_v1_DisplayResponse; @@ -194,7 +194,7 @@ extern "C" { #define wippersnapper_signal_v1_PWMRequest_init_default {{{NULL}, NULL}, 0, {wippersnapper_pwm_v1_PWMAttachRequest_init_default}} #define wippersnapper_signal_v1_PWMResponse_init_default {{{NULL}, NULL}, 0, {wippersnapper_pwm_v1_PWMAttachResponse_init_default}} #define wippersnapper_signal_v1_DisplayRequest_init_default {{{NULL}, NULL}, 0, {wippersnapper_display_v1_DisplayAddOrReplace_init_default}} -#define wippersnapper_signal_v1_DisplayResponse_init_default {{{NULL}, NULL}, 0, {wippersnapper_display_v1_DisplayAddedorReplaced_init_default}} +#define wippersnapper_signal_v1_DisplayResponse_init_default {{{NULL}, NULL}, 0, {wippersnapper_display_v1_DisplayAddedOrReplaced_init_default}} #define wippersnapper_signal_v1_UARTRequest_init_zero {{{NULL}, NULL}, 0, {wippersnapper_uart_v1_UARTDeviceAttachRequest_init_zero}} #define wippersnapper_signal_v1_UARTResponse_init_zero {{{NULL}, NULL}, 0, {wippersnapper_uart_v1_UARTDeviceAttachResponse_init_zero}} #define wippersnapper_signal_v1_Ds18x20Request_init_zero {{{NULL}, NULL}, 0, {wippersnapper_ds18x20_v1_Ds18x20InitRequest_init_zero}} @@ -210,7 +210,7 @@ extern "C" { #define wippersnapper_signal_v1_PWMRequest_init_zero {{{NULL}, NULL}, 0, {wippersnapper_pwm_v1_PWMAttachRequest_init_zero}} #define wippersnapper_signal_v1_PWMResponse_init_zero {{{NULL}, NULL}, 0, {wippersnapper_pwm_v1_PWMAttachResponse_init_zero}} #define wippersnapper_signal_v1_DisplayRequest_init_zero {{{NULL}, NULL}, 0, {wippersnapper_display_v1_DisplayAddOrReplace_init_zero}} -#define wippersnapper_signal_v1_DisplayResponse_init_zero {{{NULL}, NULL}, 0, {wippersnapper_display_v1_DisplayAddedorReplaced_init_zero}} +#define wippersnapper_signal_v1_DisplayResponse_init_zero {{{NULL}, NULL}, 0, {wippersnapper_display_v1_DisplayAddedOrReplaced_init_zero}} /* Field tags (for use in manual encoding/decoding) */ #define wippersnapper_signal_v1_CreateSignalRequest_pin_configs_tag 6 @@ -404,7 +404,7 @@ X(a, STATIC, ONEOF, MSG_W_CB, (payload,display_added,payload.display_added) X(a, STATIC, ONEOF, MSG_W_CB, (payload,display_removed,payload.display_removed), 2) #define wippersnapper_signal_v1_DisplayResponse_CALLBACK NULL #define wippersnapper_signal_v1_DisplayResponse_DEFAULT NULL -#define wippersnapper_signal_v1_DisplayResponse_payload_display_added_MSGTYPE wippersnapper_display_v1_DisplayAddedorReplaced +#define wippersnapper_signal_v1_DisplayResponse_payload_display_added_MSGTYPE wippersnapper_display_v1_DisplayAddedOrReplaced #define wippersnapper_signal_v1_DisplayResponse_payload_display_removed_MSGTYPE wippersnapper_display_v1_DisplayRemoved extern const pb_msgdesc_t wippersnapper_signal_v1_UARTRequest_msg; diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index 2f7925a88..13cbdecfd 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index 101d5bb60..166a9cff8 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Mon Aug 25 15:39:12 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From 75deb6b5c11bf19d73eedf7d8409a88c82f992a6 Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 24 Sep 2025 11:59:16 -0400 Subject: [PATCH 55/76] Draw and update status bar, show splash --- src/Wippersnapper.cpp | 4 + src/components/display/assets/icons.h | 24 + src/components/display/assets/splash.h | 2362 ++++++++++------- src/components/display/controller.cpp | 12 + src/components/display/controller.h | 1 + src/components/display/drivers/dispDrvBase.h | 55 +- .../dispDrvThinkInkGrayscale4Eaamfgn.h | 84 +- src/components/display/hardware.cpp | 14 +- src/components/display/hardware.h | 4 +- src/network_interfaces/Wippersnapper_ESP32.h | 2 +- 10 files changed, 1509 insertions(+), 1053 deletions(-) create mode 100644 src/components/display/assets/icons.h diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 459e43248..981a8198a 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2914,5 +2914,9 @@ ws_status_t Wippersnapper::run() { WS._uartComponent->update(); WS.feedWDT(); + // Process display controller events, if initialized + WS._displayController->update(); + WS.feedWDT(); + return WS_NET_CONNECTED; // TODO: Make this funcn void! } diff --git a/src/components/display/assets/icons.h b/src/components/display/assets/icons.h new file mode 100644 index 000000000..1e6209b6f --- /dev/null +++ b/src/components/display/assets/icons.h @@ -0,0 +1,24 @@ +#ifndef _ICONS_H_ +#define _ICONS_H_ +#include + +const unsigned char epd_bmp_cloud [] PROGMEM = { + // 'cloud-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0d, 0xc0, 0x18, 0x78, 0x10, 0x0c, 0x30, 0x04, 0x70, 0x0c, + 0xc0, 0x06, 0xc0, 0x03, 0xc0, 0x03, 0x40, 0x03, 0x70, 0x06, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00 +}; + +const unsigned char epd_bmp_wifi [] PROGMEM = { + // 'wifi-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x3c, 0x3c, 0x70, 0x0e, 0xc0, 0x03, 0x03, 0xc0, 0x0f, 0xf0, + 0x1c, 0x38, 0x18, 0x18, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00 +}; + + +const unsigned char epd_bmp_bat_full [] PROGMEM = { + // 'battery-full-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0xc0, 0x06, 0xff, 0xfa, 0xf0, 0x0b, 0xf0, 0x0b, + 0xf0, 0x0b, 0xf0, 0x0b, 0xff, 0xfa, 0xc0, 0x06, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +#endif // _ICONS_H_ \ No newline at end of file diff --git a/src/components/display/assets/splash.h b/src/components/display/assets/splash.h index c0eaec4fe..c9a405c2d 100644 --- a/src/components/display/assets/splash.h +++ b/src/components/display/assets/splash.h @@ -3,1016 +3,1364 @@ #include // 'adafruit_wippersnapper_logo', 240x135px -static const unsigned char tft_bitmap_ws_logo_240135 [] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf7, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xff, 0x80, 0xf3, 0xff, 0xff, 0xfb, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0x00, 0xf1, 0xff, 0xff, 0xb3, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0xc1, 0x7f, 0xff, 0x00, 0xf1, 0xff, 0xfd, 0x32, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x00, 0x7f, 0xff, 0x00, 0xf1, 0xff, 0xfd, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x00, 0x7f, - 0xfe, 0x00, 0xe0, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xfe, 0x00, - 0x60, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xfc, 0x00, 0x60, 0xff, - 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, 0xfc, 0x30, 0x60, 0x7f, 0xf0, 0x00, - 0x1e, 0x00, 0xf8, 0x00, 0x03, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x1f, 0xfc, 0x70, 0x00, 0x7f, 0xf0, 0x00, 0x1e, 0x00, - 0x70, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xfc, 0xc0, 0x00, 0x3f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, - 0x00, 0x1f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x00, 0x0f, 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x0f, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - 0x00, 0x0f, 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x00, 0x00, - 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, - 0xf8, 0xc0, 0x00, 0x1f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf0, 0x60, - 0x00, 0x1f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x1f, - 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x1f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xe0, 0x00, - 0x1f, 0xff, 0xf0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x01, 0xfc, 0x01, 0xc7, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x1e, 0x00, - 0x70, 0x01, 0xc0, 0x03, 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, - 0xe0, 0x03, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x00, 0x7c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, - 0x00, 0x1f, 0x00, 0x1c, 0x00, 0x00, 0x3c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x00, 0x07, 0xc0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x00, 0x1f, - 0x00, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, - 0x80, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x00, 0x1f, 0x00, 0x18, - 0x00, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x00, 0x1e, 0x00, 0x10, 0x00, 0x00, - 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xc0, 0x03, 0x00, 0x0e, 0x00, 0x10, 0x03, 0x80, 0x0c, 0x00, - 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x03, 0x80, 0x0c, 0x00, 0x0f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, - 0x70, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0c, 0x00, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, - 0x00, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x00, 0x00, - 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0xf0, - 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x61, 0xff, - 0xff, 0x0e, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x01, 0xf0, 0x03, 0xff, - 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfe, - 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0xff, 0x00, 0x00, 0x07, 0xf0, 0x01, 0xff, 0xfc, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, - 0x7e, 0x00, 0x70, 0x00, 0x1f, 0xff, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, 0xff, 0xf0, 0x0f, 0xff, 0x00, 0x00, 0x3e, 0x00, - 0x70, 0x01, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x7f, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, - 0xff, 0xff, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, - 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, - 0x00, 0x3f, 0x80, 0x00, 0x00, 0x03, 0xfc, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x00, 0x1f, - 0xff, 0xfc, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xfe, - 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x01, 0xf8, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0x90, 0x1f, 0x00, 0xf8, 0x03, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xff, 0x80, 0x00, - 0x7c, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf8, 0x1f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x00, 0x04, 0x07, 0xc0, 0x60, 0x00, 0xff, 0xc0, 0x01, 0x81, 0xe0, 0x7c, 0x00, - 0xf0, 0x00, 0x78, 0x00, 0x3c, 0x00, 0x0c, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xfc, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x7f, 0x80, 0x01, 0x00, 0xe0, 0x7c, 0x00, 0xf0, 0x00, - 0x38, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, - 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0x80, 0x03, 0x00, 0xe0, 0x78, 0x00, 0xf0, 0x00, 0x38, 0x00, - 0x1c, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xff, - 0xff, 0xf0, 0x00, 0x3f, 0x00, 0x03, 0x00, 0x60, 0x78, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x0c, 0x00, - 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xf0, 0x1f, 0xf8, - 0x00, 0x3f, 0x00, 0x03, 0x00, 0x60, 0x70, 0x00, 0xf0, 0x00, 0x10, 0x00, 0x08, 0x00, 0x1c, 0x00, - 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x7f, 0x80, 0x01, 0xfe, 0x00, 0x3f, - 0x03, 0xfb, 0x00, 0x60, 0x70, 0x20, 0xe0, 0x30, 0x10, 0x18, 0x08, 0x0f, 0xf8, 0x1c, 0x07, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0xfc, 0x00, 0x00, 0x7f, 0x00, 0x3e, 0x00, 0x7f, - 0x00, 0x00, 0xe0, 0x60, 0xe0, 0x38, 0x10, 0x18, 0x08, 0x00, 0x78, 0x1c, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x01, 0xf8, 0x00, 0x00, 0x3f, 0x80, 0x7e, 0x00, 0x0f, 0x00, 0x00, - 0xe0, 0x60, 0xe0, 0x30, 0x30, 0x18, 0x18, 0x00, 0x78, 0x1c, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x00, 0x00, 0x0f, 0xf8, 0xfe, 0x00, 0x06, 0x00, 0x00, 0xe0, 0x60, - 0xe0, 0x60, 0x30, 0x30, 0x18, 0x00, 0x78, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x06, 0x00, 0x00, 0xc0, 0xe0, 0xe0, 0x00, - 0x30, 0x00, 0x18, 0x00, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x02, 0x00, 0x00, 0xc0, 0xe0, 0xc0, 0x00, 0x60, 0x00, - 0x30, 0x00, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x01, 0xff, 0xff, 0xf0, 0x06, 0x04, 0x00, 0x80, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x70, 0x1f, - 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xfe, 0xfc, 0x06, 0x04, 0x00, 0x80, 0x00, 0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x1f, 0xf0, 0x00, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x30, 0x18, 0x00, 0x7f, 0xfc, - 0x00, 0x04, 0x0e, 0x00, 0x80, 0x00, 0xc0, 0x07, 0xe0, 0x03, 0xf0, 0x00, 0x70, 0x20, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x04, - 0x0e, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xe0, 0x7f, 0xf0, 0x00, 0x70, 0x30, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x0c, 0x0e, 0x01, - 0x00, 0x00, 0xc0, 0xff, 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xfc, 0x00, 0x7f, 0xfc, 0x00, 0x1c, 0x0f, 0x00, 0x03, 0xc0, - 0x80, 0xff, 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x00, 0xfc, 0x7e, 0x00, 0x7f, 0xfc, 0x00, 0x3c, 0x0f, 0x00, 0x07, 0xc0, 0x80, 0xff, - 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x01, 0xf0, 0x0f, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, - 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff -}; +static const unsigned char tft_bitmap_ws_logo_240135[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf7, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, + 0xff, 0x80, 0xf3, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0x00, 0xf1, 0xff, 0xff, 0xb3, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xc1, 0x7f, + 0xff, 0x00, 0xf1, 0xff, 0xfd, 0x32, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0x00, 0xf1, 0xff, 0xfd, 0x00, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x00, 0x7f, + 0xfe, 0x00, 0xe0, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xfe, 0x00, 0x60, 0xff, 0xf8, 0x00, + 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, + 0xfc, 0x00, 0x60, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, 0xfc, 0x30, 0x60, 0x7f, 0xf0, 0x00, + 0x1e, 0x00, 0xf8, 0x00, 0x03, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x1f, + 0xfc, 0x70, 0x00, 0x7f, 0xf0, 0x00, 0x1e, 0x00, 0x70, 0x00, 0x00, 0x7f, + 0x80, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xfc, 0xc0, 0x00, 0x3f, 0xe0, 0x00, + 0x0e, 0x00, 0x70, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, + 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x0f, + 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, + 0x0e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, + 0xf8, 0xc0, 0x00, 0x1f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf0, 0x60, 0x00, 0x1f, 0xe0, 0x00, + 0x0e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, + 0xf0, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xe0, 0x00, + 0x1f, 0xff, 0xf0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x01, + 0xfc, 0x01, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, + 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xc0, 0x03, + 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xc0, 0x00, + 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x00, + 0x7c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, + 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, + 0x00, 0x1f, 0x00, 0x1c, 0x00, 0x00, 0x3c, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x07, 0xc0, 0x00, + 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x00, 0x1f, 0x00, 0x18, 0x00, 0x00, + 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, + 0x80, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xe0, 0x03, + 0x00, 0x1f, 0x00, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x00, 0x1e, 0x00, 0x10, 0x00, 0x00, + 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xc0, 0x03, + 0x00, 0x0e, 0x00, 0x10, 0x03, 0x80, 0x0c, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x03, 0x80, + 0x0c, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0c, 0x00, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, + 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0x1f, + 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x61, 0xff, 0xff, 0x0e, 0x00, 0x00, + 0xfe, 0x00, 0x70, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x01, 0xf0, 0x03, 0xff, + 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x07, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, + 0x7e, 0x00, 0x70, 0x00, 0x1f, 0xff, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, + 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, + 0xff, 0xf0, 0x0f, 0xff, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xff, 0xff, + 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf8, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x7f, 0xc0, 0x00, + 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, + 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, + 0xe0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, + 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x03, 0xfc, 0x00, + 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xfc, 0x00, 0x00, + 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, + 0x80, 0x1f, 0xff, 0xfe, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x90, + 0x1f, 0x00, 0xf8, 0x03, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xff, 0x80, 0x00, + 0x7c, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, + 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, + 0x04, 0x07, 0xc0, 0x60, 0x00, 0xff, 0xc0, 0x01, 0x81, 0xe0, 0x7c, 0x00, + 0xf0, 0x00, 0x78, 0x00, 0x3c, 0x00, 0x0c, 0x00, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x7f, + 0x80, 0x01, 0x00, 0xe0, 0x7c, 0x00, 0xf0, 0x00, 0x38, 0x00, 0x1c, 0x00, + 0x0c, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0x80, 0x03, 0x00, 0xe0, 0x78, 0x00, + 0xf0, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x3f, + 0x00, 0x03, 0x00, 0x60, 0x78, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x0c, 0x00, + 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0x3f, 0xf0, 0x1f, 0xf8, 0x00, 0x3f, 0x00, 0x03, 0x00, 0x60, 0x70, 0x00, + 0xf0, 0x00, 0x10, 0x00, 0x08, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x7f, 0x80, 0x01, 0xfe, 0x00, 0x3f, + 0x03, 0xfb, 0x00, 0x60, 0x70, 0x20, 0xe0, 0x30, 0x10, 0x18, 0x08, 0x0f, + 0xf8, 0x1c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0xfc, 0x00, 0x00, 0x7f, 0x00, 0x3e, 0x00, 0x7f, 0x00, 0x00, 0xe0, 0x60, + 0xe0, 0x38, 0x10, 0x18, 0x08, 0x00, 0x78, 0x1c, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x01, 0xf8, 0x00, 0x00, 0x3f, 0x80, 0x7e, + 0x00, 0x0f, 0x00, 0x00, 0xe0, 0x60, 0xe0, 0x30, 0x30, 0x18, 0x18, 0x00, + 0x78, 0x1c, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0xe0, 0x00, 0x00, 0x0f, 0xf8, 0xfe, 0x00, 0x06, 0x00, 0x00, 0xe0, 0x60, + 0xe0, 0x60, 0x30, 0x30, 0x18, 0x00, 0x78, 0x00, 0x0f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, + 0x00, 0x06, 0x00, 0x00, 0xc0, 0xe0, 0xe0, 0x00, 0x30, 0x00, 0x18, 0x00, + 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x02, 0x00, 0x00, 0xc0, 0xe0, + 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, + 0xf0, 0x06, 0x04, 0x00, 0x80, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x70, 0x1f, + 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xfc, 0x06, 0x04, 0x00, 0x80, 0x00, + 0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x1f, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x30, 0x18, 0x00, 0x7f, 0xfc, + 0x00, 0x04, 0x0e, 0x00, 0x80, 0x00, 0xc0, 0x07, 0xe0, 0x03, 0xf0, 0x00, + 0x70, 0x20, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x04, 0x0e, 0x01, 0x00, 0x00, + 0xc0, 0xff, 0xe0, 0x7f, 0xf0, 0x00, 0x70, 0x30, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, + 0x00, 0x0c, 0x0e, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xc0, 0x7f, 0xe0, 0x00, + 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x00, 0x7f, 0xfc, 0x00, 0x7f, 0xfc, 0x00, 0x1c, 0x0f, 0x00, 0x03, 0xc0, + 0x80, 0xff, 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0xfc, 0x7e, 0x00, 0x7f, 0xfc, + 0x00, 0x3c, 0x0f, 0x00, 0x07, 0xc0, 0x80, 0xff, 0xc0, 0x7f, 0xe0, 0x00, + 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x01, 0xf0, 0x0f, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // 'adafruit_wippersnapper_logo', 240x240px -static const unsigned char tft_bitmap_ws_logo_240240 [] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xc0, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, - 0xff, 0x80, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0x00, - 0xf1, 0xff, 0xff, 0xb3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x89, 0xff, 0xff, 0x00, 0xf1, 0xff, - 0xff, 0x12, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0x00, 0xf0, 0xff, 0xfc, 0x00, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x7f, 0xfe, 0x00, 0xe0, 0xff, 0xfc, 0x00, 0x1f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xfe, 0x00, 0x60, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x00, 0x3f, 0xfe, 0x00, 0x60, 0x7f, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x00, 0x1f, 0xfc, 0x30, 0x60, 0x7f, 0xf0, 0x00, 0x1f, 0x00, 0xf8, 0x00, 0x07, 0xff, 0xc0, 0x00, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, - 0xfc, 0x70, 0x00, 0x7f, 0xf0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x07, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xfc, 0xc0, - 0x00, 0x3f, 0xf0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf8, 0x80, 0x00, 0x3f, - 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, - 0x0e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf8, 0xc0, 0x00, 0x1f, 0xe0, 0x00, 0x0e, 0x00, - 0x70, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf0, 0x60, 0x00, 0x1f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, - 0x00, 0x07, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xe0, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, - 0x80, 0x00, 0x00, 0x3f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, 0x80, 0x00, - 0x00, 0x3f, 0x80, 0x01, 0xfc, 0x01, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, - 0xe0, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xc0, 0x03, 0x80, 0x1e, 0x00, 0x1f, - 0x00, 0x00, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xe0, 0x00, - 0x00, 0x0f, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1f, 0x00, 0x1e, 0x00, 0x00, - 0x7c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x07, - 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1f, 0x00, 0x1c, 0x00, 0x00, 0x3c, 0x00, - 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x07, 0xc0, 0x00, - 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1f, 0x00, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x07, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, 0x80, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x1e, 0x00, - 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1f, 0x00, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, - 0xe0, 0x03, 0x80, 0x1e, 0x00, 0x10, 0x01, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xc0, 0x03, - 0x80, 0x0e, 0x00, 0x10, 0x03, 0x80, 0x0c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x80, 0x00, - 0x00, 0x30, 0x03, 0x80, 0x0c, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x30, - 0x00, 0x00, 0x0c, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, - 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, - 0x70, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x61, 0xff, 0xff, 0x0e, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, - 0x00, 0x3f, 0x80, 0x00, 0x01, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0xff, - 0x80, 0x00, 0x07, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x1f, 0xff, 0x80, 0x00, - 0xff, 0xf0, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, - 0xff, 0xe0, 0x0f, 0xff, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xf0, - 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x07, 0xfc, 0x00, - 0x00, 0x7f, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xf8, 0x00, 0x00, - 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x0f, - 0xf0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x03, 0xf8, 0x00, - 0x0e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xfc, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x0e, 0x00, - 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xfe, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x1e, 0x00, 0xf8, 0x03, - 0xff, 0xff, 0x80, 0x1f, 0xff, 0xff, 0x80, 0x00, 0x3c, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xf0, 0x1f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x04, 0x07, 0xc0, 0x60, - 0x00, 0xff, 0xc0, 0x01, 0x81, 0xe0, 0x3c, 0x00, 0xf0, 0x00, 0x78, 0x00, 0x3c, 0x00, 0x0c, 0x00, - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x7f, - 0x80, 0x01, 0x00, 0xe0, 0x7c, 0x00, 0xf0, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x0f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0x80, 0x03, - 0x00, 0xe0, 0x78, 0x00, 0xf0, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0x00, 0x03, 0x00, 0x60, - 0x78, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xf0, 0x1f, 0xf8, 0x00, 0x3f, 0x00, 0x03, 0x00, 0x60, 0x70, 0x00, - 0xf0, 0x00, 0x18, 0x00, 0x08, 0x00, 0x18, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xf8, 0x00, 0x7f, 0x80, 0x01, 0xfe, 0x00, 0x3e, 0x03, 0xfb, 0x00, 0x60, 0x70, 0x20, 0xe0, 0x30, - 0x10, 0x18, 0x08, 0x0f, 0xf8, 0x1c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, - 0xfc, 0x00, 0x00, 0x7f, 0x00, 0x3e, 0x00, 0x7f, 0x00, 0x00, 0x70, 0x60, 0xe0, 0x30, 0x10, 0x18, - 0x08, 0x00, 0x78, 0x1c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x03, 0xf8, 0x00, - 0x00, 0x1f, 0x80, 0x7e, 0x00, 0x0e, 0x00, 0x00, 0xe0, 0x60, 0xe0, 0x30, 0x30, 0x38, 0x18, 0x00, - 0x78, 0x1c, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x00, 0x00, 0x0f, - 0xf8, 0xfe, 0x00, 0x06, 0x00, 0x00, 0xe0, 0x60, 0xe0, 0x30, 0x30, 0x30, 0x18, 0x00, 0x78, 0x00, - 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, - 0x00, 0x06, 0x00, 0x00, 0xc0, 0xe0, 0xe0, 0x00, 0x30, 0x00, 0x18, 0x00, 0x78, 0x00, 0x0f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x06, - 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x06, 0x04, 0x00, - 0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x1f, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x06, 0x04, 0x00, 0x80, 0x00, - 0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x1f, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x00, 0x30, 0x18, 0x00, 0x7f, 0xfc, 0x00, 0x04, 0x06, 0x01, 0x80, 0x00, 0xc0, 0x07, - 0xe0, 0x03, 0xf0, 0x00, 0x70, 0x20, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x04, 0x0e, 0x01, 0x00, 0x00, 0x40, 0xff, 0xe0, 0x7f, - 0xf0, 0x00, 0x70, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, - 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x0c, 0x0e, 0x01, 0x00, 0x00, 0x40, 0xff, 0xe0, 0x7f, 0xe0, 0x00, - 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xfc, 0x00, - 0x7f, 0xfc, 0x00, 0x1c, 0x0f, 0x00, 0x03, 0xc0, 0x00, 0xff, 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0xfc, 0x7e, 0x00, 0x7f, 0xfc, - 0x00, 0x3c, 0x0f, 0x00, 0x07, 0xc0, 0x00, 0xff, 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xf0, 0x0f, 0x80, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, - 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, - 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; +static const unsigned char tft_bitmap_ws_logo_240240[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf7, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, + 0xff, 0x80, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0x00, 0xf1, 0xff, 0xff, 0xb3, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x89, 0xff, + 0xff, 0x00, 0xf1, 0xff, 0xff, 0x12, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0x00, 0xf0, 0xff, 0xfc, 0x00, + 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x7f, + 0xfe, 0x00, 0xe0, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xfe, 0x00, 0x60, 0xff, 0xf8, 0x00, + 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, + 0xfe, 0x00, 0x60, 0x7f, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, 0xfc, 0x30, 0x60, 0x7f, 0xf0, 0x00, + 0x1f, 0x00, 0xf8, 0x00, 0x07, 0xff, 0xc0, 0x00, 0x7f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, + 0xfc, 0x70, 0x00, 0x7f, 0xf0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x7f, + 0x80, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xfc, 0xc0, 0x00, 0x3f, 0xf0, 0x00, + 0x0e, 0x00, 0x70, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x01, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, + 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x0f, + 0x80, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, + 0x0e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x7f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, + 0xf8, 0xc0, 0x00, 0x1f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x07, + 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf0, 0x60, 0x00, 0x1f, 0xe0, 0x00, + 0x0e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, + 0xf0, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, + 0x80, 0x00, 0x00, 0x3f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xe0, 0x00, + 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x3f, 0x80, 0x01, + 0xfc, 0x01, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, + 0xe0, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xc0, 0x03, + 0x80, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xc0, 0x00, + 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1f, 0x00, 0x1e, 0x00, 0x00, + 0x7c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, + 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, + 0x80, 0x1f, 0x00, 0x1c, 0x00, 0x00, 0x3c, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x07, 0xc0, 0x00, + 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1f, 0x00, 0x18, 0x00, 0x00, + 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, + 0x80, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, + 0x80, 0x1f, 0x00, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1e, 0x00, 0x10, 0x01, 0x00, + 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xc0, 0x03, + 0x80, 0x0e, 0x00, 0x10, 0x03, 0x80, 0x0c, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x30, 0x03, 0x80, + 0x0c, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, + 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0c, 0x00, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, + 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, + 0x80, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0x1f, + 0x80, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x61, 0xff, 0xff, 0x0e, 0x00, 0x00, + 0xfe, 0x00, 0x70, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x01, 0xf0, 0x01, 0xff, + 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0xff, + 0x80, 0x00, 0x07, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, + 0x7e, 0x00, 0x70, 0x00, 0x1f, 0xff, 0x80, 0x00, 0xff, 0xf0, 0x00, 0x00, + 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, + 0xff, 0xe0, 0x0f, 0xff, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xff, 0xff, + 0x80, 0x1f, 0xff, 0xf0, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf8, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x7f, 0xc0, 0x00, + 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xf8, 0x00, 0x00, + 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, + 0xe0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, + 0x80, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x03, 0xf8, 0x00, + 0x0e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xfc, 0x00, 0x00, + 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x0e, 0x00, 0x70, 0x01, 0xff, 0xff, + 0x80, 0x1f, 0xff, 0xfe, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, + 0x1e, 0x00, 0xf8, 0x03, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xff, 0x80, 0x00, + 0x3c, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1f, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, + 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, + 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, + 0x04, 0x07, 0xc0, 0x60, 0x00, 0xff, 0xc0, 0x01, 0x81, 0xe0, 0x3c, 0x00, + 0xf0, 0x00, 0x78, 0x00, 0x3c, 0x00, 0x0c, 0x00, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x7f, + 0x80, 0x01, 0x00, 0xe0, 0x7c, 0x00, 0xf0, 0x00, 0x38, 0x00, 0x1c, 0x00, + 0x0c, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0x80, 0x03, 0x00, 0xe0, 0x78, 0x00, + 0xf0, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x3f, + 0x00, 0x03, 0x00, 0x60, 0x78, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x0c, 0x00, + 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0x3f, 0xf0, 0x1f, 0xf8, 0x00, 0x3f, 0x00, 0x03, 0x00, 0x60, 0x70, 0x00, + 0xf0, 0x00, 0x18, 0x00, 0x08, 0x00, 0x18, 0x00, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x7f, 0x80, 0x01, 0xfe, 0x00, 0x3e, + 0x03, 0xfb, 0x00, 0x60, 0x70, 0x20, 0xe0, 0x30, 0x10, 0x18, 0x08, 0x0f, + 0xf8, 0x1c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, + 0xfc, 0x00, 0x00, 0x7f, 0x00, 0x3e, 0x00, 0x7f, 0x00, 0x00, 0x70, 0x60, + 0xe0, 0x30, 0x10, 0x18, 0x08, 0x00, 0x78, 0x1c, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x03, 0xf8, 0x00, 0x00, 0x1f, 0x80, 0x7e, + 0x00, 0x0e, 0x00, 0x00, 0xe0, 0x60, 0xe0, 0x30, 0x30, 0x38, 0x18, 0x00, + 0x78, 0x1c, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, + 0xe0, 0x00, 0x00, 0x0f, 0xf8, 0xfe, 0x00, 0x06, 0x00, 0x00, 0xe0, 0x60, + 0xe0, 0x30, 0x30, 0x30, 0x18, 0x00, 0x78, 0x00, 0x0f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, + 0x00, 0x06, 0x00, 0x00, 0xc0, 0xe0, 0xe0, 0x00, 0x30, 0x00, 0x18, 0x00, + 0x78, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x06, 0x00, 0x00, 0xc0, 0xc0, + 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, + 0xf0, 0x06, 0x04, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x1f, + 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x06, 0x04, 0x00, 0x80, 0x00, + 0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x1f, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x30, 0x18, 0x00, 0x7f, 0xfc, + 0x00, 0x04, 0x06, 0x01, 0x80, 0x00, 0xc0, 0x07, 0xe0, 0x03, 0xf0, 0x00, + 0x70, 0x20, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x04, 0x0e, 0x01, 0x00, 0x00, + 0x40, 0xff, 0xe0, 0x7f, 0xf0, 0x00, 0x70, 0x30, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, + 0x00, 0x0c, 0x0e, 0x01, 0x00, 0x00, 0x40, 0xff, 0xe0, 0x7f, 0xe0, 0x00, + 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, + 0x00, 0x7f, 0xfc, 0x00, 0x7f, 0xfc, 0x00, 0x1c, 0x0f, 0x00, 0x03, 0xc0, + 0x00, 0xff, 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0xfc, 0x7e, 0x00, 0x7f, 0xfc, + 0x00, 0x3c, 0x0f, 0x00, 0x07, 0xc0, 0x00, 0xff, 0xc0, 0x7f, 0xe0, 0x00, + 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x01, 0xf0, 0x0f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // 'adafruit_wippersnapper_logo', ePD Magtag, 296x128px -static const unsigned char epd_bitmap_ws_logo_296128 [] = { - // 'adafruit_wippersnapper_logo, 296x128px - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x00, 0x03, 0xfe, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x03, 0xfc, 0x0e, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x73, 0x00, 0x00, 0x07, 0xfc, 0x0f, 0x00, - 0x00, 0x06, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x20, - 0x00, 0x07, 0xfc, 0x0f, 0x00, 0x00, 0x27, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0xff, 0x60, 0x00, 0x07, 0xfe, 0x0f, 0x00, 0x00, 0x37, 0xfe, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xff, 0xe0, 0x00, 0x0f, 0xfe, 0x1f, 0x80, 0x00, - 0x3f, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0x00, - 0x0f, 0xfe, 0x1f, 0x80, 0x00, 0x3f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1f, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0x1f, 0x80, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x00, 0x1f, 0xff, 0x3f, 0xc0, 0x00, 0x7f, - 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x1f, - 0x1f, 0x3f, 0xc0, 0x00, 0xff, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3f, 0xff, 0xf8, 0x00, 0x1c, 0x3f, 0xbf, 0xc0, 0x00, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, - 0xff, 0x00, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x38, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, - 0xe1, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x39, 0xff, - 0xff, 0xe0, 0x01, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, - 0xff, 0xfc, 0x00, 0x39, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0xff, - 0xf0, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x79, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xe1, - 0xff, 0xe1, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x79, 0xff, 0xff, - 0xf0, 0x01, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, - 0xfc, 0x00, 0x7c, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfc, - 0x3f, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0xfe, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xe0, 0xff, - 0xc1, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0xfe, 0xff, 0xff, 0xf8, - 0x03, 0xff, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xc0, 0x07, - 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, - 0x00, 0xff, 0xff, 0xff, 0xf8, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x3f, - 0xff, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xf0, 0x0f, 0xff, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x01, 0xff, 0xff, 0xff, 0xfc, 0x03, 0xff, 0xff, 0xe1, 0xff, 0xe1, - 0xff, 0xf0, 0x7f, 0xfe, 0x3f, 0xfe, 0x0f, 0xff, 0xc0, 0x7f, 0xff, 0xf8, 0x0f, 0xff, 0x7c, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x01, 0xff, 0xff, 0xff, 0xfc, 0x03, - 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc0, 0xff, 0xff, - 0xfc, 0x0f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x01, - 0xff, 0xff, 0xff, 0xfc, 0x07, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, - 0x07, 0xff, 0xc1, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1f, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, - 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc3, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xfc, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x03, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xff, - 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc3, 0xff, 0xff, 0xff, - 0x0f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x8f, 0xff, - 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, 0x07, - 0xff, 0xc7, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0x81, 0xff, 0xe1, 0xff, 0xf0, - 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc7, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x81, 0xff, 0xe1, 0xff, 0xf0, 0x7f, 0xfe, 0x3f, 0xfe, 0x0f, 0xff, 0xc7, 0xff, 0x8f, 0xff, 0x8f, - 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0xe1, 0xff, 0xf9, 0xff, 0xfe, 0x3f, 0xff, 0x1f, 0xff, - 0xcf, 0xff, 0x87, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0xe1, 0xff, 0xff, 0xff, - 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xcf, 0xff, 0x87, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, - 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0x8f, 0xff, - 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0x8f, - 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfc, - 0x3f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x01, 0xff, - 0xe1, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xfe, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0x0f, 0xff, - 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, - 0xfb, 0xff, 0xf0, 0x7f, 0xfe, 0xff, 0xff, 0xfe, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xf0, 0x3f, - 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xff, 0xff, 0xf1, 0xf8, 0x00, 0x00, 0xfc, 0x7f, 0xff, 0xfc, 0x01, 0xff, 0xe1, - 0xff, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xf8, 0x0f, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0x80, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, - 0xff, 0xfc, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0x80, - 0x00, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfe, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, - 0xff, 0x00, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0x01, 0xff, 0xe1, 0xff, - 0xf0, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0x80, 0x01, 0xff, 0xfc, 0x00, 0x0f, 0xff, - 0xff, 0x81, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, - 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xfe, 0x00, 0x1f, - 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xfe, 0x00, - 0x00, 0x07, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xf8, 0x01, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, - 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0x07, 0xff, 0xff, 0xff, 0xff, 0x00, 0x7f, 0xff, - 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0x8f, - 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x1f, 0xff, 0xff, - 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, - 0x01, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, - 0xff, 0x80, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x00, - 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xe0, - 0xff, 0xe0, 0xff, 0xf0, 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x07, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x03, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, - 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x02, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x9f, 0xff, 0xff, 0xcf, 0xff, 0xf0, 0x00, 0x7f, 0xff, 0x1f, - 0xe1, 0xff, 0x07, 0xff, 0x83, 0xff, 0xfc, 0x1f, 0xff, 0xe0, 0xff, 0xff, 0xdf, 0xff, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8e, 0x00, 0x03, 0x8f, 0xff, - 0xf8, 0x00, 0xff, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0xff, 0x81, 0xff, 0xfe, 0x0f, 0xff, 0xf0, 0xff, - 0xff, 0x8f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, - 0x80, 0x00, 0x00, 0x0f, 0xff, 0xfc, 0x01, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x07, 0xff, 0xc1, 0xff, - 0xff, 0x1f, 0xff, 0xf8, 0xff, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, 0x01, 0xff, 0xff, 0x3f, 0xf0, - 0xfe, 0x0f, 0xff, 0xc3, 0xff, 0xff, 0x9f, 0xff, 0xf8, 0xff, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, - 0x03, 0xff, 0xff, 0x3f, 0xf9, 0xfe, 0x0f, 0xff, 0xc3, 0xff, 0xff, 0x9f, 0xff, 0xfc, 0xff, 0xff, - 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfc, 0x00, - 0x3f, 0xe0, 0x01, 0xff, 0xff, 0x03, 0xff, 0xfe, 0x3f, 0xf9, 0xfe, 0x1f, 0xff, 0xc3, 0xff, 0xff, - 0x9f, 0xff, 0xfc, 0xff, 0xff, 0x9f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xff, 0xf0, 0x03, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0x03, 0xfc, 0x02, 0x3f, 0xfd, 0xfe, - 0x1f, 0xdf, 0xc3, 0xfc, 0xff, 0x9f, 0xc7, 0xfc, 0xfe, 0x00, 0x1f, 0xe3, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0x80, 0x3f, 0xfe, 0x07, - 0xff, 0x00, 0x3f, 0xfd, 0xfe, 0x3f, 0x9f, 0xc3, 0xfc, 0x7f, 0x9f, 0xc3, 0xfd, 0xfe, 0x00, 0x1f, - 0xe3, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xc0, 0x3f, 0xff, - 0xff, 0xe0, 0x1f, 0xfe, 0x07, 0xff, 0xf0, 0x7f, 0xff, 0xfc, 0x3f, 0x9f, 0xc3, 0xf8, 0x7f, 0xbf, - 0xc7, 0xf9, 0xff, 0xfc, 0x1f, 0xe3, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0xf9, 0x00, 0xff, 0xff, 0xff, 0xf8, 0x04, 0xfc, 0x07, 0xff, 0xfc, 0x7f, 0xff, 0xfc, 0x3f, - 0x9f, 0xc7, 0xf8, 0xff, 0x3f, 0xc7, 0xf9, 0xff, 0xfc, 0x1f, 0xc3, 0xfc, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x01, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x30, 0x07, 0xff, - 0xfc, 0x7f, 0xff, 0xfc, 0x7f, 0x1f, 0xc7, 0xf8, 0xff, 0x3f, 0xc7, 0xf9, 0xff, 0xfc, 0x1f, 0xff, - 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, - 0xfe, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x7f, 0xff, 0xfc, 0x7f, 0x1f, 0xc7, 0xff, 0xff, 0x3f, 0xff, - 0xf9, 0xff, 0xfc, 0x3f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0xff, 0xfe, 0x7f, 0xff, 0xfc, 0x7f, 0x1f, - 0xc7, 0xff, 0xfe, 0x3f, 0xff, 0xf1, 0xff, 0xf8, 0x3f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0xff, 0xfe, - 0x7f, 0x7f, 0xfc, 0xff, 0x3f, 0xc7, 0xff, 0xfe, 0x3f, 0xff, 0xf3, 0xff, 0xf8, 0x3f, 0xff, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, - 0xc0, 0x00, 0x00, 0x0f, 0xfe, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xcf, 0xff, 0xfc, 0x7f, 0xff, 0xe3, - 0xfc, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xfe, 0xff, 0x3f, 0xf9, 0xff, 0xff, 0xcf, - 0xff, 0xf8, 0x7f, 0xff, 0xc3, 0xfc, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x3f, 0xe7, 0xff, 0xe0, 0x00, 0x0f, 0xff, 0xfc, 0xff, - 0x3f, 0xf9, 0xff, 0xff, 0xcf, 0xff, 0xe0, 0x7f, 0xff, 0x03, 0xff, 0xfe, 0x3f, 0x9f, 0xe0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x1f, 0xc3, 0xff, 0xf0, - 0x00, 0x0f, 0xff, 0xfc, 0xff, 0x1f, 0xf9, 0xff, 0xff, 0xcf, 0xf0, 0x00, 0x7f, 0x80, 0x03, 0xff, - 0xfc, 0x7f, 0x9f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, - 0xfe, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xf8, 0xfe, 0x1f, 0xfb, 0xff, 0xff, 0xcf, 0xf0, - 0x00, 0x7f, 0x00, 0x07, 0xff, 0xfc, 0x7f, 0x9f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xf9, 0xfe, 0x1f, - 0xfb, 0xff, 0xff, 0xcf, 0xe0, 0x00, 0xff, 0x00, 0x07, 0xff, 0xfc, 0x7f, 0x9f, 0xe0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x01, 0xff, 0xf0, 0x00, - 0x1f, 0xff, 0xf1, 0xfe, 0x0f, 0xf7, 0xf8, 0x1f, 0xdf, 0xe0, 0x00, 0xff, 0x00, 0x07, 0xff, 0xfc, - 0x7f, 0x9f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, - 0x02, 0x00, 0xff, 0xe0, 0x00, 0x0f, 0xff, 0xc1, 0xfe, 0x0f, 0xf7, 0xf8, 0x1f, 0xff, 0xe0, 0x00, - 0xff, 0x00, 0x07, 0xff, 0xfc, 0x7f, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x3f, 0xf0, 0x3f, 0xe0, 0x7f, 0xc0, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x7f, 0xf0, 0x07, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, - 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; +static const unsigned char epd_bitmap_ws_logo_296128[] = { + // 'adafruit_wippersnapper_logo, 296x128px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xfe, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, + 0x00, 0x00, 0x03, 0xfe, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x22, 0x00, 0x00, 0x03, 0xfc, 0x0e, 0x00, 0x00, 0x02, 0x20, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x73, 0x00, 0x00, 0x07, 0xfc, 0x0f, 0x00, 0x00, 0x06, 0x72, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x77, 0x20, 0x00, 0x07, 0xfc, 0x0f, 0x00, 0x00, 0x27, 0x76, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x03, 0xff, 0x60, 0x00, 0x07, 0xfe, 0x0f, 0x00, 0x00, 0x37, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x17, 0xff, 0xe0, 0x00, 0x0f, 0xfe, 0x1f, 0x80, 0x00, + 0x3f, 0xff, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xe0, 0x00, 0x0f, 0xfe, 0x1f, 0x80, + 0x00, 0x3f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0x1f, + 0x80, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x00, 0x1f, 0xff, + 0x3f, 0xc0, 0x00, 0x7f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x1f, + 0x1f, 0x3f, 0xc0, 0x00, 0xff, 0xff, 0xc0, 0xff, 0xc0, 0xff, 0xff, 0xf0, + 0x00, 0x0f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xf8, 0x00, + 0x1c, 0x3f, 0xbf, 0xc0, 0x00, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, + 0xff, 0x00, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, + 0x00, 0x38, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, + 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, + 0xfc, 0x00, 0x39, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xe1, 0xff, 0xe1, + 0xff, 0xff, 0xff, 0xe0, 0x3f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0xff, 0xfc, 0x00, 0x39, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xff, 0xe1, 0xff, + 0xe1, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0xff, 0xfc, 0x00, 0x79, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, 0xe1, + 0xff, 0xe1, 0xff, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x79, 0xff, 0xff, 0xf0, 0x01, 0xff, 0xff, + 0xe1, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0x7c, 0xff, 0xff, 0xf0, 0x01, 0xff, + 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfc, 0x00, 0xfe, 0xff, 0xff, 0xf8, 0x03, + 0xff, 0xff, 0xe0, 0xff, 0xc1, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, + 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0xfe, 0xff, 0xff, 0xf8, + 0x03, 0xff, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, + 0xff, 0xff, 0xc0, 0x07, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x00, 0xff, 0xff, 0xff, + 0xf8, 0x03, 0xff, 0xff, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x3f, + 0xff, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xf0, 0x0f, 0xff, 0x1c, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x01, 0xff, 0xff, + 0xff, 0xfc, 0x03, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x7f, 0xfe, + 0x3f, 0xfe, 0x0f, 0xff, 0xc0, 0x7f, 0xff, 0xf8, 0x0f, 0xff, 0x7c, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x01, 0xff, + 0xff, 0xff, 0xfc, 0x03, 0xff, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x3f, + 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc0, 0xff, 0xff, 0xfc, 0x0f, 0xff, 0xfc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0x01, + 0xff, 0xff, 0xff, 0xfc, 0x07, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, + 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc1, 0xff, 0xff, 0xfe, 0x0f, 0xff, + 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, + 0x03, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, + 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc3, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, + 0xff, 0x03, 0xff, 0xff, 0xff, 0xfe, 0x07, 0xff, 0xff, 0xc1, 0xff, 0xe1, + 0xff, 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc3, 0xff, 0xff, 0xff, + 0x0f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xc1, 0xff, + 0xe1, 0xff, 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc7, 0xff, 0xff, + 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1f, 0xff, 0xff, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xef, 0xff, 0xff, 0x81, + 0xff, 0xe1, 0xff, 0xf0, 0x3f, 0xfe, 0x3f, 0xfe, 0x07, 0xff, 0xc7, 0xff, + 0xff, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x81, 0xff, 0xe1, 0xff, 0xf0, 0x7f, 0xfe, 0x3f, 0xfe, 0x0f, 0xff, 0xc7, + 0xff, 0x8f, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x81, 0xff, 0xe1, 0xff, 0xf9, 0xff, 0xfe, 0x3f, 0xff, 0x1f, 0xff, + 0xcf, 0xff, 0x87, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0x81, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, 0xff, + 0xff, 0xcf, 0xff, 0x87, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfe, 0x3f, 0xff, + 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfc, 0x3f, + 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, 0xfc, + 0x3f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x01, 0xff, 0xe1, 0xff, 0xff, 0xff, + 0xf8, 0x3f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x01, 0xff, 0xe1, 0xff, 0xff, + 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x8f, 0xff, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, + 0xfb, 0xff, 0xf0, 0x7f, 0xfe, 0xff, 0xff, 0xfe, 0x01, 0xff, 0xe1, 0xff, + 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xff, 0xfe, 0x0f, 0xff, 0xff, 0xff, 0x8f, + 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, + 0xff, 0xf1, 0xf8, 0x00, 0x00, 0xfc, 0x7f, 0xff, 0xfc, 0x01, 0xff, 0xe1, + 0xff, 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xf8, 0x0f, 0xff, 0xff, 0xfe, + 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfc, 0x01, 0xff, + 0xe1, 0xff, 0xff, 0xff, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0x80, + 0x00, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfe, 0x01, + 0xff, 0xe1, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xff, 0x00, 0x0f, 0xff, + 0xff, 0xff, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, + 0x01, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x07, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0f, 0xff, 0xff, 0x80, 0x01, 0xff, 0xfc, 0x00, 0x0f, 0xff, + 0xff, 0x81, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xfe, 0x00, 0x00, + 0x07, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0xff, 0xfe, 0x00, 0x1f, 0xff, 0xff, 0xc0, 0x03, + 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xfe, 0x00, + 0x00, 0x07, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xf8, + 0x01, 0xff, 0xff, 0xc1, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, 0xfe, + 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xf0, 0x07, 0xff, 0xff, 0xff, + 0xff, 0x00, 0x7f, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, 0x3f, + 0xfe, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x1f, 0xff, 0xff, + 0xff, 0xff, 0xc0, 0x3f, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x00, 0x00, + 0x3f, 0xfe, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0x8f, 0xff, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x80, 0x7f, 0xff, + 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xe1, 0xff, 0xe1, 0xff, 0xf0, 0x00, + 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xf8, 0x07, 0xff, 0xe0, 0xff, 0xe0, 0xff, 0xf0, + 0x00, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xfe, 0x07, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x03, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, + 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x1f, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, + 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x9f, 0xff, 0xff, 0xcf, 0xff, 0xf0, + 0x00, 0x7f, 0xff, 0x1f, 0xe1, 0xff, 0x07, 0xff, 0x83, 0xff, 0xfc, 0x1f, + 0xff, 0xe0, 0xff, 0xff, 0xdf, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8e, 0x00, 0x03, 0x8f, 0xff, + 0xf8, 0x00, 0xff, 0xff, 0x1f, 0xe0, 0xff, 0x07, 0xff, 0x81, 0xff, 0xfe, + 0x0f, 0xff, 0xf0, 0xff, 0xff, 0x8f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x80, 0x00, 0x00, 0x0f, + 0xff, 0xfc, 0x01, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0x07, 0xff, 0xc1, 0xff, + 0xff, 0x1f, 0xff, 0xf8, 0xff, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, + 0x07, 0xff, 0xfe, 0x01, 0xff, 0xff, 0x3f, 0xf0, 0xfe, 0x0f, 0xff, 0xc3, + 0xff, 0xff, 0x9f, 0xff, 0xf8, 0xff, 0xff, 0x8f, 0xff, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, + 0x00, 0x03, 0xff, 0xfe, 0x03, 0xff, 0xff, 0x3f, 0xf9, 0xfe, 0x0f, 0xff, + 0xc3, 0xff, 0xff, 0x9f, 0xff, 0xfc, 0xff, 0xff, 0x8f, 0xff, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfc, 0x00, + 0x3f, 0xe0, 0x01, 0xff, 0xff, 0x03, 0xff, 0xfe, 0x3f, 0xf9, 0xfe, 0x1f, + 0xff, 0xc3, 0xff, 0xff, 0x9f, 0xff, 0xfc, 0xff, 0xff, 0x9f, 0xff, 0xfc, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, + 0x03, 0xff, 0xfe, 0x00, 0x7f, 0xff, 0x03, 0xfc, 0x02, 0x3f, 0xfd, 0xfe, + 0x1f, 0xdf, 0xc3, 0xfc, 0xff, 0x9f, 0xc7, 0xfc, 0xfe, 0x00, 0x1f, 0xe3, + 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, + 0xe0, 0x0f, 0xff, 0xff, 0x80, 0x3f, 0xfe, 0x07, 0xff, 0x00, 0x3f, 0xfd, + 0xfe, 0x3f, 0x9f, 0xc3, 0xfc, 0x7f, 0x9f, 0xc3, 0xfd, 0xfe, 0x00, 0x1f, + 0xe3, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xff, 0xc0, 0x3f, 0xff, 0xff, 0xe0, 0x1f, 0xfe, 0x07, 0xff, 0xf0, 0x7f, + 0xff, 0xfc, 0x3f, 0x9f, 0xc3, 0xf8, 0x7f, 0xbf, 0xc7, 0xf9, 0xff, 0xfc, + 0x1f, 0xe3, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0xf9, 0x00, 0xff, 0xff, 0xff, 0xf8, 0x04, 0xfc, 0x07, 0xff, 0xfc, + 0x7f, 0xff, 0xfc, 0x3f, 0x9f, 0xc7, 0xf8, 0xff, 0x3f, 0xc7, 0xf9, 0xff, + 0xfc, 0x1f, 0xc3, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x60, 0x01, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x30, 0x07, 0xff, + 0xfc, 0x7f, 0xff, 0xfc, 0x7f, 0x1f, 0xc7, 0xf8, 0xff, 0x3f, 0xc7, 0xf9, + 0xff, 0xfc, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x03, + 0xff, 0xfe, 0x7f, 0xff, 0xfc, 0x7f, 0x1f, 0xc7, 0xff, 0xff, 0x3f, 0xff, + 0xf9, 0xff, 0xfc, 0x3f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, + 0x01, 0xff, 0xfe, 0x7f, 0xff, 0xfc, 0x7f, 0x1f, 0xc7, 0xff, 0xfe, 0x3f, + 0xff, 0xf1, 0xff, 0xf8, 0x3f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x80, + 0x00, 0x00, 0xff, 0xfe, 0x7f, 0x7f, 0xfc, 0xff, 0x3f, 0xc7, 0xff, 0xfe, + 0x3f, 0xff, 0xf3, 0xff, 0xf8, 0x3f, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, + 0xc0, 0x00, 0x00, 0x0f, 0xfe, 0xff, 0x3f, 0xf8, 0xff, 0xff, 0xcf, 0xff, + 0xfc, 0x7f, 0xff, 0xe3, 0xfc, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, + 0xff, 0xe0, 0x00, 0x00, 0x01, 0xfe, 0xff, 0x3f, 0xf9, 0xff, 0xff, 0xcf, + 0xff, 0xf8, 0x7f, 0xff, 0xc3, 0xfc, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x3f, + 0xe7, 0xff, 0xe0, 0x00, 0x0f, 0xff, 0xfc, 0xff, 0x3f, 0xf9, 0xff, 0xff, + 0xcf, 0xff, 0xe0, 0x7f, 0xff, 0x03, 0xff, 0xfe, 0x3f, 0x9f, 0xe0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, + 0x1f, 0xc3, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xfc, 0xff, 0x1f, 0xf9, 0xff, + 0xff, 0xcf, 0xf0, 0x00, 0x7f, 0x80, 0x03, 0xff, 0xfc, 0x7f, 0x9f, 0xe0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xfe, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xf8, 0xfe, 0x1f, 0xfb, + 0xff, 0xff, 0xcf, 0xf0, 0x00, 0x7f, 0x00, 0x07, 0xff, 0xfc, 0x7f, 0x9f, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0xfe, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xf9, 0xfe, 0x1f, + 0xfb, 0xff, 0xff, 0xcf, 0xe0, 0x00, 0xff, 0x00, 0x07, 0xff, 0xfc, 0x7f, + 0x9f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0xfc, 0x00, 0x01, 0xff, 0xf0, 0x00, 0x1f, 0xff, 0xf1, 0xfe, + 0x0f, 0xf7, 0xf8, 0x1f, 0xdf, 0xe0, 0x00, 0xff, 0x00, 0x07, 0xff, 0xfc, + 0x7f, 0x9f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0xf8, 0x02, 0x00, 0xff, 0xe0, 0x00, 0x0f, 0xff, 0xc1, + 0xfe, 0x0f, 0xf7, 0xf8, 0x1f, 0xff, 0xe0, 0x00, 0xff, 0x00, 0x07, 0xff, + 0xfc, 0x7f, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x3f, 0xf0, 0x3f, 0xe0, 0x7f, 0xc0, 0x00, 0x00, 0x7e, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x7f, 0xf0, 0x07, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, + 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char epd_bmp_cloud[] PROGMEM = { + // 'cloud-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0d, 0xc0, 0x18, 0x78, 0x10, + 0x0c, 0x30, 0x04, 0x70, 0x0c, 0xc0, 0x06, 0xc0, 0x03, 0xc0, 0x03, + 0x40, 0x03, 0x70, 0x06, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char epd_bmp_wifi[] PROGMEM = { + // 'wifi-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x3c, 0x3c, 0x70, 0x0e, 0xc0, + 0x03, 0x03, 0xc0, 0x0f, 0xf0, 0x1c, 0x38, 0x18, 0x18, 0x00, 0x00, + 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char epd_bmp_bat_full[] PROGMEM = { + // 'battery-full-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0xc0, 0x06, 0xff, + 0xfa, 0xf0, 0x0b, 0xf0, 0x0b, 0xf0, 0x0b, 0xf0, 0x0b, 0xff, 0xfa, + 0xc0, 0x06, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #endif // SPLASH_H \ No newline at end of file diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index e51e04f7d..63b507341 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -129,4 +129,16 @@ bool DisplayController::Handle_Display_Write( WS_DEBUG_PRINTLN(msgWrite->message); display->writeMessage(msgWrite->message); return true; +} + +void DisplayController::update() { + // if _hw_instances is empty, early out + if (_hw_instances.size() == 0) + return; + + // Get the driver instance for the display + DisplayHardware *display = nullptr; + for (auto &hw_instance : _hw_instances) { + hw_instance->updateStatusBar(WS.getRSSI(), 100, WS.networkStatus()); + } } \ No newline at end of file diff --git a/src/components/display/controller.h b/src/components/display/controller.h index f4c087e30..e795655b0 100644 --- a/src/components/display/controller.h +++ b/src/components/display/controller.h @@ -35,6 +35,7 @@ class DisplayController { wippersnapper_display_v1_DisplayAddOrReplace *msgAdd); bool Handle_Display_Remove(wippersnapper_display_v1_DisplayRemove *msgRemove); bool Handle_Display_Write(wippersnapper_display_v1_DisplayWrite *msgWrite); + void update(); private: std::vector diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index babd15e05..74def55ae 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -15,9 +15,10 @@ #ifndef WS_DISP_DRV_BASE_H #define WS_DISP_DRV_BASE_H +#include "../assets/icons.h" +#include "../assets/splash.h" #include "Adafruit_ThinkInk.h" #include "Wippersnapper.h" -#include "../assets/splash.h" /*! @brief Abstract base class for display drivers. @@ -125,32 +126,54 @@ class dispDrvBase { */ virtual void setTextSize(uint8_t s) { _text_sz = s; } - /*! @brief Displays a splash screen on the display. @note This method can be overridden by derived classes to provide specific functionality. */ - virtual void showSplash() { // No-op for base class + virtual void showSplash() { // No-op for base class + } + + /*! + @brief Draws a status bar at the top of the display. + @param io_username + The username to display on the status bar. + @note This method can be overridden by derived classes to provide + specific functionality. + */ + virtual void drawStatusBar(const char *io_username) { + // No-op for base class } - virtual void drawStatusBar() { + /*! + @brief Updates the status bar with current information (battery level, + connectivity status, etc). + @note This method can be overridden by derived classes to provide + specific functionality. + */ + virtual void updateStatusBar(int8_t rssi, uint8_t bat, + ws_status_t mqtt_connected) { // No-op for base class } protected: - int16_t _pin_dc; ///< Data/Command pin - int16_t _pin_rst; ///< Reset pin - int16_t _pin_cs; ///< Chip Select pin - int16_t _pin_busy; ///< Optional Busy pin - int16_t _pin_sram_cs; ///< Optional EPD SRAM chip select pin - uint16_t _pin_mosi; ///< Optional MOSI pin for SPI TFT displays - uint16_t _pin_miso; ///< Optional MISO pin for SPI TFT displays - uint16_t _pin_sck; ///< Optional SCK pin for SPI TFT displays - uint8_t _text_sz = 1; ///< Text size for displaying a message - int16_t _height; ///< Height of the display - int16_t _width; ///< Width of the display - uint8_t _rotation; ///< Rotation of the display + int16_t _pin_dc; ///< Data/Command pin + int16_t _pin_rst; ///< Reset pin + int16_t _pin_cs; ///< Chip Select pin + int16_t _pin_busy; ///< Optional Busy pin + int16_t _pin_sram_cs; ///< Optional EPD SRAM chip select pin + uint16_t _pin_mosi; ///< Optional MOSI pin for SPI TFT displays + uint16_t _pin_miso; ///< Optional MISO pin for SPI TFT displays + uint16_t _pin_sck; ///< Optional SCK pin for SPI TFT displays + uint8_t _text_sz = 1; ///< Text size for displaying a message + int16_t _height; ///< Height of the display + int16_t _width; ///< Width of the display + uint8_t _rotation; ///< Rotation of the display + int8_t _statusbar_rssi; ///< RSSI value for status bar + uint8_t + _statusbar_bat; ///< Battery level, as a percentage, for the status bar + ws_status_t + _statusbar_mqtt_connected; ///< MQTT connection status for the status bar }; #endif // WS_DISP_DRV_BASE_H \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index cc95d1101..179dc8196 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -79,8 +79,8 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { /*! @brief Displays a splash screen */ - virtual void showSplash() override { - if (! _display) + virtual void showSplash() override { + if (!_display) return; _display->drawBitmap(0, 0, epd_bitmap_ws_logo_296128, 296, 128, EPD_BLACK); _display->display(); @@ -90,32 +90,68 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { /*! @brief Draws a status bar at the top of the display. */ - virtual void drawStatusBar() override { + virtual void drawStatusBar(const char *io_username) override { if (!_display) return; - _display->clearBuffer(); - _display->fillScreen(EPD_WHITE); - - int barHeight = 15; + + // Draw status bar + int barHeight = 20; // Assumes 16x16 icons int borderWidth = 1; - // Black rect outline - _display->fillRect(0, 0, _width, barHeight, EPD_BLACK); - // White rect inside for icons/text - _display->fillRect(borderWidth, borderWidth, - _width - (2 * borderWidth), - barHeight - (2 * borderWidth), - EPD_WHITE); - - // Vertically center text in the bar - _display->setTextSize(1); // Text size 1 = 8 pixels tall - int textHeight = 8; - int usableHeight = barHeight - (2 * borderWidth); // 13px usable - int textY = borderWidth + (usableHeight - textHeight) / 2; // = 1 + (13-8)/2 = 3 - // Draw status text + _display->fillRect(0, 0, _display->width(), barHeight, EPD_BLACK); + _display->fillRect(borderWidth, borderWidth, + _display->width() - (2 * borderWidth), + barHeight - (2 * borderWidth), EPD_WHITE); + + // Draw username on left side of the status bar + _display->setTextSize(1); _display->setTextColor(EPD_BLACK); - _display->setCursor(5, textY); - _display->print("[IO] OK|[WiFi] OK|[Bat] 100%"); - _display->display(); + _display->setCursor(5, 6); + _display->print(io_username); + + // Calculate icon positions and center vertically + int iconSize = 16; + int iconSpacing = 4; + int rightMargin = 5; + int iconY = borderWidth + ((barHeight - 2 * borderWidth - iconSize) / 2); + int batteryX = _display->width() - iconSize - rightMargin; + int wifiX = batteryX - iconSize - iconSpacing; + int cloudX = wifiX - iconSize - iconSpacing; + // Draw icons on right side of the status bar + _display->drawBitmap(cloudX, iconY, epd_bmp_cloud, iconSize, iconSize, + EPD_BLACK); + _display->drawBitmap(wifiX, iconY, epd_bmp_wifi, iconSize, iconSize, + EPD_BLACK); + _display->drawBitmap(batteryX, iconY, epd_bmp_bat_full, iconSize, iconSize, + EPD_BLACK); + } + + /*! + @brief Updates the status bar with current information (battery level, + connectivity status, etc). + @param rssi + The current RSSI value to display. + @param bat + The current battery level (0-100) to display. + @param mqtt_connected + The current MQTT connection status to display. + */ + void updateStatusBar(int8_t rssi, uint8_t bat, + ws_status_t mqtt_connected) override { + if (!_display) + return; + + if (bat != _statusbar_bat) { + // Update battery icon + _statusbar_bat = bat; + } + if (rssi != _statusbar_rssi) { + // Update WiFi icon + _statusbar_rssi = rssi; + } + if (mqtt_connected != _statusbar_mqtt_connected) { + // Update cloud icon + _statusbar_mqtt_connected = mqtt_connected; + } } /*! diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index bbfe418e1..62ac9f752 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -262,14 +262,22 @@ bool DisplayHardware::beginEPD( void DisplayHardware::showSplash() { if (!_drvDisp) - return; + return; _drvDisp->showSplash(); } -void DisplayHardware::drawStatusBar() { - _drvDisp->drawStatusBar(); +void DisplayHardware::drawStatusBar(const char *io_username) { + if (!_drvDisp) + return; + _drvDisp->drawStatusBar(const char *io_username); } +void DisplayHardware::updateStatusBar(int8_t rssi, uint8_t bat, + ws_status_t mqtt_connected) { + if (!_drvDisp) + return; + _drvDisp->updateStatusBar(rssi, bat, mqtt_connected); +} /*! @brief Removes a suffix from the hardware instance name, if it exists. diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index b20075355..77c9c91b6 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -44,9 +44,9 @@ class DisplayHardware { bool beginTft(wippersnapper_display_v1_TftConfig *config, wippersnapper_display_v1_TftSpiConfig *spi_config); - void showSplash(); - void drawStatusBar(); + void drawStatusBar(const char *io_username); + void updateStatusBar(int8_t rssi, uint8_t bat, ws_status_t mqtt_connected); // // API for Adafruit_GFX that abstracts hardware functionality // NOTE: These methods are meant to be implemented within dispDrvBase and diff --git a/src/network_interfaces/Wippersnapper_ESP32.h b/src/network_interfaces/Wippersnapper_ESP32.h index 81c87995c..dc251fe3c 100644 --- a/src/network_interfaces/Wippersnapper_ESP32.h +++ b/src/network_interfaces/Wippersnapper_ESP32.h @@ -8,7 +8,7 @@ * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * - * Copyright (c) Brent Rubell 2020-2024 for Adafruit Industries. + * Copyright (c) Brent Rubell 2020-2025 for Adafruit Industries. * * MIT license, all text here must be included in any redistribution. * From bab1f2b1eba3ed245acd11aa994f4fd743d32e5d Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 25 Sep 2025 11:58:03 -0400 Subject: [PATCH 56/76] Status work --- src/Wippersnapper.cpp | 2 +- src/components/display/assets/icons.h | 27 ++++- src/components/display/assets/splash.h | 18 --- src/components/display/controller.cpp | 8 +- src/components/display/controller.h | 2 +- src/components/display/drivers/dispDrvBase.h | 11 +- .../dispDrvThinkInkGrayscale4Eaamfgn.h | 111 ++++++++++++------ src/components/display/hardware.cpp | 4 +- src/components/display/hardware.h | 2 +- 9 files changed, 119 insertions(+), 66 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 981a8198a..fd50b1842 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2915,7 +2915,7 @@ ws_status_t Wippersnapper::run() { WS.feedWDT(); // Process display controller events, if initialized - WS._displayController->update(); + WS._displayController->update(getRSSI(), networkStatus() == WS_CONNECTED); WS.feedWDT(); return WS_NET_CONNECTED; // TODO: Make this funcn void! diff --git a/src/components/display/assets/icons.h b/src/components/display/assets/icons.h index 1e6209b6f..656decbf1 100644 --- a/src/components/display/assets/icons.h +++ b/src/components/display/assets/icons.h @@ -2,18 +2,41 @@ #define _ICONS_H_ #include -const unsigned char epd_bmp_cloud [] PROGMEM = { +const unsigned char epd_bmp_cloud_online [] PROGMEM = { // 'cloud-thin-full, 16x16px 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0d, 0xc0, 0x18, 0x78, 0x10, 0x0c, 0x30, 0x04, 0x70, 0x0c, 0xc0, 0x06, 0xc0, 0x03, 0xc0, 0x03, 0x40, 0x03, 0x70, 0x06, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00 }; -const unsigned char epd_bmp_wifi [] PROGMEM = { +const unsigned char epd_bmp_cloud_offline [] PROGMEM = { + // 'cloud-xmark-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0d, 0xc0, 0x18, 0x78, 0x10, 0x0c, 0x30, 0x04, 0x73, 0xcc, + 0xe3, 0x86, 0xc3, 0xc3, 0xc3, 0xc3, 0x40, 0x03, 0x70, 0x06, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00 +}; + +const unsigned char epd_bmp_wifi_full [] PROGMEM = { // 'wifi-thin-full, 16x16px 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x3c, 0x3c, 0x70, 0x0e, 0xc0, 0x03, 0x03, 0xc0, 0x0f, 0xf0, 0x1c, 0x38, 0x18, 0x18, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00 }; +const unsigned char epd_bmp_wifi_fair [] PROGMEM = { + // 'wifi-fair-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x0f, 0xf0, + 0x1c, 0x38, 0x18, 0x18, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00 +}; + +const unsigned char epd_bmp_wifi_weak [] PROGMEM = { + // 'wifi-weak-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00 +}; + +const unsigned char epd_bmp_wifi_no_signal [] PROGMEM = { + // 'wifi-slash-thin-full, 16x16px + 0x00, 0x00, 0x40, 0x00, 0x27, 0xc0, 0x1e, 0x38, 0x68, 0x00, 0x44, 0x03, 0x03, 0x00, 0x01, 0xe0, + 0x08, 0x90, 0x00, 0x40, 0x00, 0x20, 0x01, 0x90, 0x03, 0x88, 0x01, 0x84, 0x00, 0x02, 0x00, 0x00 +}; const unsigned char epd_bmp_bat_full [] PROGMEM = { // 'battery-full-thin-full, 16x16px diff --git a/src/components/display/assets/splash.h b/src/components/display/assets/splash.h index c9a405c2d..5109397cb 100644 --- a/src/components/display/assets/splash.h +++ b/src/components/display/assets/splash.h @@ -1345,22 +1345,4 @@ static const unsigned char epd_bitmap_ws_logo_296128[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -const unsigned char epd_bmp_cloud[] PROGMEM = { - // 'cloud-thin-full, 16x16px - 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0d, 0xc0, 0x18, 0x78, 0x10, - 0x0c, 0x30, 0x04, 0x70, 0x0c, 0xc0, 0x06, 0xc0, 0x03, 0xc0, 0x03, - 0x40, 0x03, 0x70, 0x06, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00}; - -const unsigned char epd_bmp_wifi[] PROGMEM = { - // 'wifi-thin-full, 16x16px - 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x3c, 0x3c, 0x70, 0x0e, 0xc0, - 0x03, 0x03, 0xc0, 0x0f, 0xf0, 0x1c, 0x38, 0x18, 0x18, 0x00, 0x00, - 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00}; - -const unsigned char epd_bmp_bat_full[] PROGMEM = { - // 'battery-full-thin-full, 16x16px - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0xc0, 0x06, 0xff, - 0xfa, 0xf0, 0x0b, 0xf0, 0x0b, 0xf0, 0x0b, 0xf0, 0x0b, 0xff, 0xfa, - 0xc0, 0x06, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - #endif // SPLASH_H \ No newline at end of file diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 63b507341..0b7349d99 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -72,7 +72,7 @@ bool DisplayController::Handle_Display_AddOrReplace( WS.feedWDT(); display->showSplash(); WS.feedWDT(); - display->drawStatusBar(); + display->drawStatusBar(WS._config.aio_user); WS.feedWDT(); _hw_instances.push_back(display); // Store the display instance @@ -131,7 +131,7 @@ bool DisplayController::Handle_Display_Write( return true; } -void DisplayController::update() { +void DisplayController::update(int32_t rssi, bool is_connected) { // if _hw_instances is empty, early out if (_hw_instances.size() == 0) return; @@ -139,6 +139,8 @@ void DisplayController::update() { // Get the driver instance for the display DisplayHardware *display = nullptr; for (auto &hw_instance : _hw_instances) { - hw_instance->updateStatusBar(WS.getRSSI(), 100, WS.networkStatus()); + // Note: For now, battery is always 100% as we don't have a way to read it + // yet. + hw_instance->updateStatusBar(rssi, 100, is_connected); } } \ No newline at end of file diff --git a/src/components/display/controller.h b/src/components/display/controller.h index e795655b0..eff8e38fa 100644 --- a/src/components/display/controller.h +++ b/src/components/display/controller.h @@ -35,7 +35,7 @@ class DisplayController { wippersnapper_display_v1_DisplayAddOrReplace *msgAdd); bool Handle_Display_Remove(wippersnapper_display_v1_DisplayRemove *msgRemove); bool Handle_Display_Write(wippersnapper_display_v1_DisplayWrite *msgWrite); - void update(); + void update(int32_t rssi, bool is_connected); private: std::vector diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index 74def55ae..906494d21 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -148,11 +148,17 @@ class dispDrvBase { /*! @brief Updates the status bar with current information (battery level, connectivity status, etc). + @param rssi + The current WiFi RSSI (signal strength) in dB. + @param bat + The current battery level as a percentage (0-100). + @param mqtt_status + The current MQTT connection status. @note This method can be overridden by derived classes to provide specific functionality. */ virtual void updateStatusBar(int8_t rssi, uint8_t bat, - ws_status_t mqtt_connected) { + bool mqtt_status) { // No-op for base class } @@ -172,8 +178,7 @@ class dispDrvBase { int8_t _statusbar_rssi; ///< RSSI value for status bar uint8_t _statusbar_bat; ///< Battery level, as a percentage, for the status bar - ws_status_t - _statusbar_mqtt_connected; ///< MQTT connection status for the status bar + bool _statusbar_mqtt_connected; ///< MQTT connection status for the status bar }; #endif // WS_DISP_DRV_BASE_H \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index 179dc8196..0fb32a287 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -18,6 +18,10 @@ #include "dispDrvBase.h" +#define STATUS_BAR_HEIGHT 20 ///< Height of the status bar in pixels, assumes 16px icons +#define STATUS_BAR_BORDER 1 ///< Border around the status bar in pixels +#define STATUS_BAR_ICON_SZ 16 ///< Size of status bar icons in pixels + /*! @brief Driver for a ThinkInk 2.9" Grayscale 4-level EAAMFGN display. */ @@ -84,7 +88,6 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { return; _display->drawBitmap(0, 0, epd_bitmap_ws_logo_296128, 296, 128, EPD_BLACK); _display->display(); - delay(50); } /*! @@ -94,13 +97,14 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { if (!_display) return; + // Clear the entire display buffer to remove splash screen + _display->clearBuffer(); + // Draw status bar - int barHeight = 20; // Assumes 16x16 icons - int borderWidth = 1; - _display->fillRect(0, 0, _display->width(), barHeight, EPD_BLACK); - _display->fillRect(borderWidth, borderWidth, - _display->width() - (2 * borderWidth), - barHeight - (2 * borderWidth), EPD_WHITE); + _display->fillRect(0, 0, _display->width(), STATUS_BAR_HEIGHT, EPD_BLACK); + _display->fillRect(STATUS_BAR_BORDER, STATUS_BAR_BORDER, + _display->width() - (2 * STATUS_BAR_BORDER), + STATUS_BAR_HEIGHT - (2 * STATUS_BAR_BORDER), EPD_WHITE); // Draw username on left side of the status bar _display->setTextSize(1); @@ -109,49 +113,86 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { _display->print(io_username); // Calculate icon positions and center vertically - int iconSize = 16; int iconSpacing = 4; int rightMargin = 5; - int iconY = borderWidth + ((barHeight - 2 * borderWidth - iconSize) / 2); - int batteryX = _display->width() - iconSize - rightMargin; - int wifiX = batteryX - iconSize - iconSpacing; - int cloudX = wifiX - iconSize - iconSpacing; + int iconY = STATUS_BAR_BORDER + ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2); + int batteryX = _display->width() - STATUS_BAR_ICON_SZ - rightMargin; + int wifiX = batteryX - STATUS_BAR_ICON_SZ - iconSpacing; + int cloudX = wifiX - STATUS_BAR_ICON_SZ - iconSpacing; // Draw icons on right side of the status bar - _display->drawBitmap(cloudX, iconY, epd_bmp_cloud, iconSize, iconSize, - EPD_BLACK); - _display->drawBitmap(wifiX, iconY, epd_bmp_wifi, iconSize, iconSize, - EPD_BLACK); - _display->drawBitmap(batteryX, iconY, epd_bmp_bat_full, iconSize, iconSize, - EPD_BLACK); + _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_full, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + _display->drawBitmap(batteryX, iconY, epd_bmp_bat_full, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + + _display->display(); } - /*! + /*! @brief Updates the status bar with current information (battery level, connectivity status, etc). @param rssi - The current RSSI value to display. + The current WiFi RSSI (signal strength) in dB. @param bat - The current battery level (0-100) to display. - @param mqtt_connected - The current MQTT connection status to display. + The current battery level as a percentage (0-100). + @param mqtt_status + The current MQTT connection status. */ - void updateStatusBar(int8_t rssi, uint8_t bat, - ws_status_t mqtt_connected) override { + void updateStatusBar(int8_t rssi, uint8_t bat, bool mqtt_status) override { if (!_display) return; - if (bat != _statusbar_bat) { - // Update battery icon - _statusbar_bat = bat; + bool do_update = false; + // Update cloud icon only if it changed + if (mqtt_status != _statusbar_mqtt_connected) { + int iconSpacing = 4; + int rightMargin = 5; + int iconY = STATUS_BAR_BORDER + ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2); + int batteryX = _display->width() - STATUS_BAR_ICON_SZ - rightMargin; + int wifiX = batteryX - STATUS_BAR_ICON_SZ - iconSpacing; + int cloudX = wifiX - STATUS_BAR_ICON_SZ - iconSpacing; + + // Clear and draw the new cloud icon, based on MQTT connection status + _display->fillRect(cloudX, iconY, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_WHITE); + if (mqtt_status == 21) { + _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, + EPD_BLACK); + } else { + _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_offline, STATUS_BAR_ICON_SZ, + STATUS_BAR_ICON_SZ, EPD_BLACK); } - if (rssi != _statusbar_rssi) { - // Update WiFi icon + _statusbar_mqtt_connected = mqtt_status; + do_update = true; + } + +/* // Update WiFi icon only if it changed significantly (+/- 3 dB) + if (abs(rssi - _statusbar_rssi) >= 3 || rssi == 0 || _statusbar_rssi == 0) { + int iconSpacing = 4; + int rightMargin = 5; + int iconY = STATUS_BAR_BORDER + ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2); + int batteryX = _display->width() - STATUS_BAR_ICON_SZ - rightMargin; + int wifiX = batteryX - STATUS_BAR_ICON_SZ - iconSpacing; + + // Clear and draw the new WiFi icon, based on RSSI + _display->fillRect(wifiX, iconY, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_WHITE); + if (rssi == 0) { + _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_no_signal, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + } else if (rssi > -50) { + _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_full, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + } else if (rssi > -60) { + _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_fair, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + } else if (rssi > -70) { + _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_weak, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + } else { + _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_weak, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + } _statusbar_rssi = rssi; - } - if (mqtt_connected != _statusbar_mqtt_connected) { - // Update cloud icon - _statusbar_mqtt_connected = mqtt_connected; - } + do_update = true; + } */ + + // Temporarily removed while I get clarification on how often to refresh the epd + /* if (do_update) + _display->display(); */ + } /*! diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 62ac9f752..454969d9c 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -269,11 +269,11 @@ void DisplayHardware::showSplash() { void DisplayHardware::drawStatusBar(const char *io_username) { if (!_drvDisp) return; - _drvDisp->drawStatusBar(const char *io_username); + _drvDisp->drawStatusBar(io_username); } void DisplayHardware::updateStatusBar(int8_t rssi, uint8_t bat, - ws_status_t mqtt_connected) { + bool mqtt_connected) { if (!_drvDisp) return; _drvDisp->updateStatusBar(rssi, bat, mqtt_connected); diff --git a/src/components/display/hardware.h b/src/components/display/hardware.h index 77c9c91b6..66403a710 100644 --- a/src/components/display/hardware.h +++ b/src/components/display/hardware.h @@ -46,7 +46,7 @@ class DisplayHardware { void showSplash(); void drawStatusBar(const char *io_username); - void updateStatusBar(int8_t rssi, uint8_t bat, ws_status_t mqtt_connected); + void updateStatusBar(int8_t rssi, uint8_t bat, bool mqtt_connected); // // API for Adafruit_GFX that abstracts hardware functionality // NOTE: These methods are meant to be implemented within dispDrvBase and From 8ba32f8c73633b976b1e7a1d9f683d20148f358a Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 26 Sep 2025 11:50:34 -0400 Subject: [PATCH 57/76] Working on MagTag, remove ProtoMq harness code --- src/Wippersnapper.cpp | 2 +- src/components/display/assets/splash.h | 4 +- .../display/drivers/dispDrvSt7789.h | 106 +++++++++++++++- .../dispDrvThinkInkGrayscale4Eaamfgn.h | 109 ++++++++--------- src/components/display/hardware.cpp | 8 +- .../register/Wippersnapper_Register.cpp | 2 +- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 7 +- src/wippersnapper/display/v1/display.pb.h | 115 ++++++++++-------- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 4 +- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 26 files changed, 250 insertions(+), 141 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index fd50b1842..68158a017 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2826,7 +2826,7 @@ void Wippersnapper::connect() { WS._analogIO = new Wippersnapper_AnalogIO(5, 3.3); // Configure hardware - WS.pinCfgCompleted = true; + // WS.pinCfgCompleted = true; while (!WS.pinCfgCompleted) { WS_DEBUG_PRINTLN( "Polling for message containing hardware configuration..."); diff --git a/src/components/display/assets/splash.h b/src/components/display/assets/splash.h index 5109397cb..a8e5b7514 100644 --- a/src/components/display/assets/splash.h +++ b/src/components/display/assets/splash.h @@ -3,7 +3,7 @@ #include // 'adafruit_wippersnapper_logo', 240x135px -static const unsigned char tft_bitmap_ws_logo_240135[] = { +static const unsigned char tft_bmp_logo_240135[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -344,7 +344,7 @@ static const unsigned char tft_bitmap_ws_logo_240135[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // 'adafruit_wippersnapper_logo', 240x240px -static const unsigned char tft_bitmap_ws_logo_240240[] = { +static const unsigned char tft_bmp_logo_240240[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index ae5428548..4fd6eb29d 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -98,6 +98,104 @@ class dispDrvSt7789 : public dispDrvBase { _display->setTextSize(s); } + /*! + @brief Displays the splash screen on the display. + */ + void showSplash() override { + if (!_display) + return; + + // Display the appropriate splash screen based on resolution + if (_width == 240 && _height == 240) { + _display->drawBitmap(0, 0, tft_bmp_logo_240240, 240, 240, ST77XX_BLACK); + } else if (_width == 240 && _height == 135) { + _display->drawBitmap(0, 0, tft_bmp_logo_240135, 240, 135, EPD_BLACK); + } else { + // Unsupported resolution + return; + } + + delay(1000); + } + + /*! + @brief Draws a status bar at the top of the display. + */ + virtual void drawStatusBar(const char *io_username) override { + if (!_display) + return; + + // Configure status bar parameters based on resolution + if (_width == 240 && _height == 240) { + _status_bar_height = 20; + _status_bar_icon_sz = 16; + _status_bar_icon_spacing = 4; + _status_bar_icon_margin = 5; + } else if (_width == 240 && _height == 135) { + // TODO: The required icons are not added/implemented for 12px icons + _status_bar_height = 16; + _status_bar_icon_sz = 12; + _status_bar_icon_spacing = 3; + _status_bar_icon_margin = 4; + } else { + // Unsupported resolution + return; + } + + // Clear the entire display buffer to remove splash screen + _display->fillScreen(ST77XX_BLACK); + + // Draw status bar + // TODO: We are not drawing a border here because it isnt + // required on a color display, I think. + _display->fillRect(0, 0, _display->width(), _status_bar_height, + ST77XX_BLACK); + + // Draw username on left side of the status bar + _display->setTextSize(1); + _display->setTextColor(EPD_BLACK); + _display->setCursor(5, 6); + _display->print(io_username); + + // Calculate icon positions and center vertically + int iconY = (_status_bar_height - _status_bar_icon_sz) / 2; + int batteryX = + _display->width() - _status_bar_icon_sz - _status_bar_icon_margin; + int wifiX = batteryX - _status_bar_icon_sz - _status_bar_icon_spacing; + int cloudX = wifiX - _status_bar_icon_sz - _status_bar_icon_spacing; + if (_height == 240) { + // Draw 16px icons on right side of the status bar + _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, + _status_bar_icon_sz, _status_bar_icon_sz, EPD_BLACK); + _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_full, _status_bar_icon_sz, + _status_bar_icon_sz, EPD_BLACK); + _display->drawBitmap(batteryX, iconY, epd_bmp_bat_full, + _status_bar_icon_sz, _status_bar_icon_sz, EPD_BLACK); + } else if (_height == 135) { + // TODO: Draw 12px icons on right side of the status bar + } else { + // Unsupported resolution + return; + } + } + + /*! + @brief Updates the status bar with current information (battery level, + connectivity status, etc). + @param rssi + The current WiFi RSSI (signal strength) in dB. + @param bat + The current battery level as a percentage (0-100). + @param mqtt_status + The current MQTT connection status. +*/ + void updateStatusBar(int8_t rssi, uint8_t bat, bool mqtt_status) override { + if (!_display) + return; + + // TODO - needs to be implemented! + } + /*! @brief Writes a message to the display. @param message @@ -111,7 +209,7 @@ class dispDrvSt7789 : public dispDrvBase { // Start with a fresh display buffer _display->fillScreen(ST77XX_BLACK); - int16_t y_idx = 0; + int16_t y_idx = _status_bar_height; _display->setCursor(0, y_idx); // Calculate the line height based on the text size (NOTE: base height is @@ -152,6 +250,12 @@ class dispDrvSt7789 : public dispDrvBase { private: Adafruit_ST7789 *_display; + uint8_t _status_bar_height; ///< Height of the status bar, in pixels + uint8_t _status_bar_icon_sz; ///< Size of status bar icons, in pixels + uint8_t + _status_bar_icon_spacing; ///< Spacing between status bar icons, in pixels + uint8_t + _status_bar_icon_margin; ///< Right margin for status bar icons, in pixels }; #endif // WS_DISP_DRV_ST7789 \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index 0fb32a287..c5c7d2f55 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -18,8 +18,9 @@ #include "dispDrvBase.h" -#define STATUS_BAR_HEIGHT 20 ///< Height of the status bar in pixels, assumes 16px icons -#define STATUS_BAR_BORDER 1 ///< Border around the status bar in pixels +#define STATUS_BAR_HEIGHT \ + 20 ///< Height of the status bar in pixels, assumes 16px icons +#define STATUS_BAR_BORDER 1 ///< Border around the status bar in pixels #define STATUS_BAR_ICON_SZ 16 ///< Size of status bar icons in pixels /*! @@ -115,84 +116,69 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { // Calculate icon positions and center vertically int iconSpacing = 4; int rightMargin = 5; - int iconY = STATUS_BAR_BORDER + ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2); + int iconY = + STATUS_BAR_BORDER + + ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2); int batteryX = _display->width() - STATUS_BAR_ICON_SZ - rightMargin; int wifiX = batteryX - STATUS_BAR_ICON_SZ - iconSpacing; int cloudX = wifiX - STATUS_BAR_ICON_SZ - iconSpacing; // Draw icons on right side of the status bar - _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); - _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_full, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); - _display->drawBitmap(batteryX, iconY, epd_bmp_bat_full, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, + STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_full, STATUS_BAR_ICON_SZ, + STATUS_BAR_ICON_SZ, EPD_BLACK); + _display->drawBitmap(batteryX, iconY, epd_bmp_bat_full, STATUS_BAR_ICON_SZ, + STATUS_BAR_ICON_SZ, EPD_BLACK); _display->display(); } - /*! - @brief Updates the status bar with current information (battery level, - connectivity status, etc). - @param rssi - The current WiFi RSSI (signal strength) in dB. - @param bat - The current battery level as a percentage (0-100). - @param mqtt_status - The current MQTT connection status. - */ + /*! + @brief Updates the status bar with current information (battery level, + connectivity status, etc). + @param rssi + The current WiFi RSSI (signal strength) in dB. + @param bat + The current battery level as a percentage (0-100). + @param mqtt_status + The current MQTT connection status. +*/ void updateStatusBar(int8_t rssi, uint8_t bat, bool mqtt_status) override { if (!_display) return; - bool do_update = false; - // Update cloud icon only if it changed - if (mqtt_status != _statusbar_mqtt_connected) { - int iconSpacing = 4; - int rightMargin = 5; - int iconY = STATUS_BAR_BORDER + ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2); - int batteryX = _display->width() - STATUS_BAR_ICON_SZ - rightMargin; - int wifiX = batteryX - STATUS_BAR_ICON_SZ - iconSpacing; - int cloudX = wifiX - STATUS_BAR_ICON_SZ - iconSpacing; + bool do_update = false; - // Clear and draw the new cloud icon, based on MQTT connection status - _display->fillRect(cloudX, iconY, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_WHITE); - if (mqtt_status == 21) { - _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, - EPD_BLACK); - } else { - _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_offline, STATUS_BAR_ICON_SZ, - STATUS_BAR_ICON_SZ, EPD_BLACK); - } - _statusbar_mqtt_connected = mqtt_status; - do_update = true; - } + // For EPD - redraws take 1-2 seconds, so only update the cloud state -/* // Update WiFi icon only if it changed significantly (+/- 3 dB) - if (abs(rssi - _statusbar_rssi) >= 3 || rssi == 0 || _statusbar_rssi == 0) { + // Update cloud icon only if it changed state + if (mqtt_status != _statusbar_mqtt_connected) { int iconSpacing = 4; int rightMargin = 5; - int iconY = STATUS_BAR_BORDER + ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2); + int iconY = + STATUS_BAR_BORDER + + ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / + 2); int batteryX = _display->width() - STATUS_BAR_ICON_SZ - rightMargin; int wifiX = batteryX - STATUS_BAR_ICON_SZ - iconSpacing; - - // Clear and draw the new WiFi icon, based on RSSI - _display->fillRect(wifiX, iconY, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_WHITE); - if (rssi == 0) { - _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_no_signal, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); - } else if (rssi > -50) { - _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_full, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); - } else if (rssi > -60) { - _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_fair, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); - } else if (rssi > -70) { - _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_weak, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + int cloudX = wifiX - STATUS_BAR_ICON_SZ - iconSpacing; + + // Clear and draw the new cloud icon, based on MQTT connection status + _display->fillRect(cloudX, iconY, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, + EPD_WHITE); + if (mqtt_status == 21) { + _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, + STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); } else { - _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_weak, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_offline, + STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); } - _statusbar_rssi = rssi; + _statusbar_mqtt_connected = mqtt_status; do_update = true; - } */ - - // Temporarily removed while I get clarification on how often to refresh the epd - /* if (do_update) - _display->display(); */ + } + if (do_update) + _display->display(); } /*! @@ -206,9 +192,10 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { if (_display == nullptr) return; - // Start with a fresh display buffer - _display->clearBuffer(); - int16_t y_idx = 0; + // Clear only the area below the status bar + _display->fillRect(0, STATUS_BAR_HEIGHT, _display->width(), + _display->height() - STATUS_BAR_HEIGHT, EPD_WHITE); + int16_t y_idx = STATUS_BAR_HEIGHT; _display->setCursor(0, y_idx); // Calculate the line height based on the text size (NOTE: base height is diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 454969d9c..1f04447d3 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -23,7 +23,7 @@ using FnCreateDispDrvEpd = // Factory for creating a new display drivers // NOTE: When you add a new display driver, make sure to add it to the factory! static const std::map FactoryDrvDispEpd = { - {"thinkink-gs4-eaamfgn", + {"eink-29-grayscale-ssd1680", [](int16_t dc, int16_t rst, int16_t cs, int16_t sram_cs, int16_t busy) -> dispDrvBase * { return new drvDispThinkInkGrayscale4Eaamfgn(dc, rst, cs, sram_cs, busy); @@ -216,8 +216,8 @@ bool DisplayHardware::beginEPD( return false; } - // For "magtag" component name, attempt to autodetect the driver type - if (strncmp(_name, "magtag", 6) == 0) { +/* // For "magtag" component name, attempt to autodetect the driver type + if (strncmp(_name, "eink-29-grayscale-ssd1680", 6) == 0) { if (detect_ssd1680(cs, dc, rst)) { // Detected SSD1680, use EAAMFGN driver strncpy(_name, "thinkink-gs4-eaamfgn", sizeof(_name) - 1); @@ -227,7 +227,7 @@ bool DisplayHardware::beginEPD( strncpy(_name, "thinkink-gs4-t5", sizeof(_name) - 1); _name[sizeof(_name) - 1] = '\0'; } - } + } */ // Create display driver object using the factory function _drvDisp = CreateDrvDispEpd(_name, dc, rst, cs, srcs, busy); diff --git a/src/components/register/Wippersnapper_Register.cpp b/src/components/register/Wippersnapper_Register.cpp index 3d9b4b401..738f05cca 100644 --- a/src/components/register/Wippersnapper_Register.cpp +++ b/src/components/register/Wippersnapper_Register.cpp @@ -77,7 +77,7 @@ bool Wippersnapper::encodePubRegistrationReq() { /****************************************************************************/ void Wippersnapper::pollRegistrationResp() { // Blocking loop, WDT reset upon failure. - WS._boardStatus = WS_BOARD_DEF_OK; + //WS._boardStatus = WS_BOARD_DEF_OK; while (WS._boardStatus != WS_BOARD_DEF_OK) { WS_DEBUG_PRINT("Polling for registration message response..."); WS_DEBUG_PRINTLN(WS._boardStatus); diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index 503fdf674..2b54f9002 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index c1f79b6b0..2373d1001 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 2cd13f48a..87204989a 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -9,10 +9,10 @@ PB_BIND(wippersnapper_display_v1_EpdSpiConfig, wippersnapper_display_v1_EpdSpiConfig, AUTO) -PB_BIND(wippersnapper_display_v1_EPDConfig, wippersnapper_display_v1_EPDConfig, AUTO) +PB_BIND(wippersnapper_display_v1_EPDWriteOptions, wippersnapper_display_v1_EPDWriteOptions, AUTO) -PB_BIND(wippersnapper_display_v1_EPDWriteOptions, wippersnapper_display_v1_EPDWriteOptions, AUTO) +PB_BIND(wippersnapper_display_v1_EPDConfig, wippersnapper_display_v1_EPDConfig, AUTO) PB_BIND(wippersnapper_display_v1_TftSpiConfig, wippersnapper_display_v1_TftSpiConfig, AUTO) @@ -39,3 +39,4 @@ PB_BIND(wippersnapper_display_v1_DisplayRemoved, wippersnapper_display_v1_Displa + diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index 68571d7d8..3e49c4e1a 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -13,9 +13,8 @@ /* Enum definitions */ typedef enum _wippersnapper_display_v1_DisplayType { wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_UNSPECIFIED = 0, - wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_OLED = 1, - wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_EPD = 2, - wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_TFT = 3 + wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_EPD = 1, + wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_TFT = 2 } wippersnapper_display_v1_DisplayType; typedef enum _wippersnapper_display_v1_EPDMode { @@ -24,6 +23,13 @@ typedef enum _wippersnapper_display_v1_EPDMode { wippersnapper_display_v1_EPDMode_EPD_MODE_MONO = 2 } wippersnapper_display_v1_EPDMode; +typedef enum _wippersnapper_display_v1_DisplayDriver { + wippersnapper_display_v1_DisplayDriver_DISPLAY_DRIVER_UNSPECIFIED = 0, + wippersnapper_display_v1_DisplayDriver_DISPLAY_DRIVER_EPD_SSD1680 = 1, + wippersnapper_display_v1_DisplayDriver_DISPLAY_DRIVER_EPD_ILI0373 = 2, + wippersnapper_display_v1_DisplayDriver_DISPLAY_DRIVER_TFT_ST7789 = 3 +} wippersnapper_display_v1_DisplayDriver; + /* Struct definitions */ typedef struct _wippersnapper_display_v1_DisplayAddedOrReplaced { char name[64]; @@ -39,9 +45,10 @@ typedef struct _wippersnapper_display_v1_DisplayRemoved { bool did_remove; } wippersnapper_display_v1_DisplayRemoved; -typedef struct _wippersnapper_display_v1_EPDConfig { - wippersnapper_display_v1_EPDMode mode; -} wippersnapper_display_v1_EPDConfig; +typedef struct _wippersnapper_display_v1_DisplayWrite { + char name[64]; + char message[1024]; +} wippersnapper_display_v1_DisplayWrite; typedef struct _wippersnapper_display_v1_EPDWriteOptions { int32_t text_size; @@ -72,8 +79,17 @@ typedef struct _wippersnapper_display_v1_TftSpiConfig { char pin_miso[6]; } wippersnapper_display_v1_TftSpiConfig; +typedef struct _wippersnapper_display_v1_EPDConfig { + wippersnapper_display_v1_EPDMode mode; + bool has_options; + wippersnapper_display_v1_EPDWriteOptions options; + int32_t width; + int32_t height; +} wippersnapper_display_v1_EPDConfig; + typedef struct _wippersnapper_display_v1_DisplayAddOrReplace { wippersnapper_display_v1_DisplayType type; + wippersnapper_display_v1_DisplayDriver driver; char name[64]; pb_size_t which_interface_type; union { @@ -87,15 +103,6 @@ typedef struct _wippersnapper_display_v1_DisplayAddOrReplace { } config; } wippersnapper_display_v1_DisplayAddOrReplace; -typedef struct _wippersnapper_display_v1_DisplayWrite { - char name[64]; - char message[1024]; - pb_size_t which_options; - union { - wippersnapper_display_v1_EPDWriteOptions epd_options; - } options; -} wippersnapper_display_v1_DisplayWrite; - /* Helper constants for enums */ #define _wippersnapper_display_v1_DisplayType_MIN wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_UNSPECIFIED @@ -106,6 +113,10 @@ typedef struct _wippersnapper_display_v1_DisplayWrite { #define _wippersnapper_display_v1_EPDMode_MAX wippersnapper_display_v1_EPDMode_EPD_MODE_MONO #define _wippersnapper_display_v1_EPDMode_ARRAYSIZE ((wippersnapper_display_v1_EPDMode)(wippersnapper_display_v1_EPDMode_EPD_MODE_MONO+1)) +#define _wippersnapper_display_v1_DisplayDriver_MIN wippersnapper_display_v1_DisplayDriver_DISPLAY_DRIVER_UNSPECIFIED +#define _wippersnapper_display_v1_DisplayDriver_MAX wippersnapper_display_v1_DisplayDriver_DISPLAY_DRIVER_TFT_ST7789 +#define _wippersnapper_display_v1_DisplayDriver_ARRAYSIZE ((wippersnapper_display_v1_DisplayDriver)(wippersnapper_display_v1_DisplayDriver_DISPLAY_DRIVER_TFT_ST7789+1)) + #ifdef __cplusplus extern "C" { @@ -113,23 +124,23 @@ extern "C" { /* Initializer values for message structs */ #define wippersnapper_display_v1_EpdSpiConfig_init_default {0, "", "", "", "", ""} -#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN} #define wippersnapper_display_v1_EPDWriteOptions_init_default {0} +#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN, false, wippersnapper_display_v1_EPDWriteOptions_init_default, 0, 0} #define wippersnapper_display_v1_TftSpiConfig_init_default {0, "", "", "", "", "", ""} #define wippersnapper_display_v1_TftConfig_init_default {0, 0, 0} -#define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} +#define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, _wippersnapper_display_v1_DisplayDriver_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} #define wippersnapper_display_v1_DisplayRemove_init_default {""} -#define wippersnapper_display_v1_DisplayWrite_init_default {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_default}} +#define wippersnapper_display_v1_DisplayWrite_init_default {"", ""} #define wippersnapper_display_v1_DisplayAddedOrReplaced_init_default {"", 0} #define wippersnapper_display_v1_DisplayRemoved_init_default {"", 0} #define wippersnapper_display_v1_EpdSpiConfig_init_zero {0, "", "", "", "", ""} -#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN} #define wippersnapper_display_v1_EPDWriteOptions_init_zero {0} +#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN, false, wippersnapper_display_v1_EPDWriteOptions_init_zero, 0, 0} #define wippersnapper_display_v1_TftSpiConfig_init_zero {0, "", "", "", "", "", ""} #define wippersnapper_display_v1_TftConfig_init_zero {0, 0, 0} -#define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} +#define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, _wippersnapper_display_v1_DisplayDriver_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} #define wippersnapper_display_v1_DisplayRemove_init_zero {""} -#define wippersnapper_display_v1_DisplayWrite_init_zero {"", "", 0, {wippersnapper_display_v1_EPDWriteOptions_init_zero}} +#define wippersnapper_display_v1_DisplayWrite_init_zero {"", ""} #define wippersnapper_display_v1_DisplayAddedOrReplaced_init_zero {"", 0} #define wippersnapper_display_v1_DisplayRemoved_init_zero {"", 0} @@ -139,7 +150,8 @@ extern "C" { #define wippersnapper_display_v1_DisplayRemove_name_tag 1 #define wippersnapper_display_v1_DisplayRemoved_name_tag 1 #define wippersnapper_display_v1_DisplayRemoved_did_remove_tag 2 -#define wippersnapper_display_v1_EPDConfig_mode_tag 1 +#define wippersnapper_display_v1_DisplayWrite_name_tag 1 +#define wippersnapper_display_v1_DisplayWrite_message_tag 2 #define wippersnapper_display_v1_EPDWriteOptions_text_size_tag 1 #define wippersnapper_display_v1_EpdSpiConfig_bus_tag 1 #define wippersnapper_display_v1_EpdSpiConfig_pin_dc_tag 2 @@ -157,15 +169,17 @@ extern "C" { #define wippersnapper_display_v1_TftSpiConfig_pin_sck_tag 5 #define wippersnapper_display_v1_TftSpiConfig_pin_rst_tag 6 #define wippersnapper_display_v1_TftSpiConfig_pin_miso_tag 7 +#define wippersnapper_display_v1_EPDConfig_mode_tag 1 +#define wippersnapper_display_v1_EPDConfig_options_tag 2 +#define wippersnapper_display_v1_EPDConfig_width_tag 3 +#define wippersnapper_display_v1_EPDConfig_height_tag 4 #define wippersnapper_display_v1_DisplayAddOrReplace_type_tag 1 -#define wippersnapper_display_v1_DisplayAddOrReplace_name_tag 2 -#define wippersnapper_display_v1_DisplayAddOrReplace_spi_epd_tag 3 -#define wippersnapper_display_v1_DisplayAddOrReplace_spi_tft_tag 4 -#define wippersnapper_display_v1_DisplayAddOrReplace_config_epd_tag 5 -#define wippersnapper_display_v1_DisplayAddOrReplace_config_tft_tag 6 -#define wippersnapper_display_v1_DisplayWrite_name_tag 1 -#define wippersnapper_display_v1_DisplayWrite_message_tag 2 -#define wippersnapper_display_v1_DisplayWrite_epd_options_tag 3 +#define wippersnapper_display_v1_DisplayAddOrReplace_driver_tag 2 +#define wippersnapper_display_v1_DisplayAddOrReplace_name_tag 3 +#define wippersnapper_display_v1_DisplayAddOrReplace_spi_epd_tag 4 +#define wippersnapper_display_v1_DisplayAddOrReplace_spi_tft_tag 5 +#define wippersnapper_display_v1_DisplayAddOrReplace_config_epd_tag 6 +#define wippersnapper_display_v1_DisplayAddOrReplace_config_tft_tag 7 /* Struct field encoding specification for nanopb */ #define wippersnapper_display_v1_EpdSpiConfig_FIELDLIST(X, a) \ @@ -178,16 +192,20 @@ X(a, STATIC, SINGULAR, STRING, pin_busy, 6) #define wippersnapper_display_v1_EpdSpiConfig_CALLBACK NULL #define wippersnapper_display_v1_EpdSpiConfig_DEFAULT NULL -#define wippersnapper_display_v1_EPDConfig_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, UENUM, mode, 1) -#define wippersnapper_display_v1_EPDConfig_CALLBACK NULL -#define wippersnapper_display_v1_EPDConfig_DEFAULT NULL - #define wippersnapper_display_v1_EPDWriteOptions_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, text_size, 1) #define wippersnapper_display_v1_EPDWriteOptions_CALLBACK NULL #define wippersnapper_display_v1_EPDWriteOptions_DEFAULT NULL +#define wippersnapper_display_v1_EPDConfig_FIELDLIST(X, a) \ +X(a, STATIC, SINGULAR, UENUM, mode, 1) \ +X(a, STATIC, OPTIONAL, MESSAGE, options, 2) \ +X(a, STATIC, SINGULAR, INT32, width, 3) \ +X(a, STATIC, SINGULAR, INT32, height, 4) +#define wippersnapper_display_v1_EPDConfig_CALLBACK NULL +#define wippersnapper_display_v1_EPDConfig_DEFAULT NULL +#define wippersnapper_display_v1_EPDConfig_options_MSGTYPE wippersnapper_display_v1_EPDWriteOptions + #define wippersnapper_display_v1_TftSpiConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, bus, 1) \ X(a, STATIC, SINGULAR, STRING, pin_cs, 2) \ @@ -208,11 +226,12 @@ X(a, STATIC, SINGULAR, INT32, rotation, 3) #define wippersnapper_display_v1_DisplayAddOrReplace_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, type, 1) \ -X(a, STATIC, SINGULAR, STRING, name, 2) \ -X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_epd,interface_type.spi_epd), 3) \ -X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_tft,interface_type.spi_tft), 4) \ -X(a, STATIC, ONEOF, MESSAGE, (config,config_epd,config.config_epd), 5) \ -X(a, STATIC, ONEOF, MESSAGE, (config,config_tft,config.config_tft), 6) +X(a, STATIC, SINGULAR, UENUM, driver, 2) \ +X(a, STATIC, SINGULAR, STRING, name, 3) \ +X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_epd,interface_type.spi_epd), 4) \ +X(a, STATIC, ONEOF, MESSAGE, (interface_type,spi_tft,interface_type.spi_tft), 5) \ +X(a, STATIC, ONEOF, MESSAGE, (config,config_epd,config.config_epd), 6) \ +X(a, STATIC, ONEOF, MESSAGE, (config,config_tft,config.config_tft), 7) #define wippersnapper_display_v1_DisplayAddOrReplace_CALLBACK NULL #define wippersnapper_display_v1_DisplayAddOrReplace_DEFAULT NULL #define wippersnapper_display_v1_DisplayAddOrReplace_interface_type_spi_epd_MSGTYPE wippersnapper_display_v1_EpdSpiConfig @@ -227,11 +246,9 @@ X(a, STATIC, SINGULAR, STRING, name, 1) #define wippersnapper_display_v1_DisplayWrite_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, name, 1) \ -X(a, STATIC, SINGULAR, STRING, message, 2) \ -X(a, STATIC, ONEOF, MESSAGE, (options,epd_options,options.epd_options), 3) +X(a, STATIC, SINGULAR, STRING, message, 2) #define wippersnapper_display_v1_DisplayWrite_CALLBACK NULL #define wippersnapper_display_v1_DisplayWrite_DEFAULT NULL -#define wippersnapper_display_v1_DisplayWrite_options_epd_options_MSGTYPE wippersnapper_display_v1_EPDWriteOptions #define wippersnapper_display_v1_DisplayAddedOrReplaced_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, STRING, name, 1) \ @@ -246,8 +263,8 @@ X(a, STATIC, SINGULAR, BOOL, did_remove, 2) #define wippersnapper_display_v1_DisplayRemoved_DEFAULT NULL extern const pb_msgdesc_t wippersnapper_display_v1_EpdSpiConfig_msg; -extern const pb_msgdesc_t wippersnapper_display_v1_EPDConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_EPDWriteOptions_msg; +extern const pb_msgdesc_t wippersnapper_display_v1_EPDConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_TftSpiConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_TftConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_DisplayAddOrReplace_msg; @@ -258,8 +275,8 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define wippersnapper_display_v1_EpdSpiConfig_fields &wippersnapper_display_v1_EpdSpiConfig_msg -#define wippersnapper_display_v1_EPDConfig_fields &wippersnapper_display_v1_EPDConfig_msg #define wippersnapper_display_v1_EPDWriteOptions_fields &wippersnapper_display_v1_EPDWriteOptions_msg +#define wippersnapper_display_v1_EPDConfig_fields &wippersnapper_display_v1_EPDConfig_msg #define wippersnapper_display_v1_TftSpiConfig_fields &wippersnapper_display_v1_TftSpiConfig_msg #define wippersnapper_display_v1_TftConfig_fields &wippersnapper_display_v1_TftConfig_msg #define wippersnapper_display_v1_DisplayAddOrReplace_fields &wippersnapper_display_v1_DisplayAddOrReplace_msg @@ -270,13 +287,13 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; /* Maximum encoded size of messages (where known) */ #define wippersnapper_display_v1_EpdSpiConfig_size 46 -#define wippersnapper_display_v1_EPDConfig_size 2 #define wippersnapper_display_v1_EPDWriteOptions_size 11 +#define wippersnapper_display_v1_EPDConfig_size 37 #define wippersnapper_display_v1_TftSpiConfig_size 53 #define wippersnapper_display_v1_TftConfig_size 33 -#define wippersnapper_display_v1_DisplayAddOrReplace_size 157 +#define wippersnapper_display_v1_DisplayAddOrReplace_size 163 #define wippersnapper_display_v1_DisplayRemove_size 65 -#define wippersnapper_display_v1_DisplayWrite_size 1104 +#define wippersnapper_display_v1_DisplayWrite_size 1091 #define wippersnapper_display_v1_DisplayAddedOrReplaced_size 67 #define wippersnapper_display_v1_DisplayRemoved_size 67 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index b01507408..0f7d99046 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index 34bbd4dc3..74db2d97c 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index 359d37d3d..835db99c1 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 6bc1db36c..887ac4877 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 4de40d222..06d9e03ba 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index d07dc0df7..c9d1eaf1c 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index 083400a2e..b506de3f9 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index e8e278326..c580f0b39 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index 365c961fd..0894fa333 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index b117989ec..d626095e6 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index a09513361..65bc7d9a2 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index cd6b7fc66..24adc6293 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index a9bd94a43..44017e6df 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 0838dae8b..164d582ad 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED @@ -463,7 +463,7 @@ union wippersnapper_signal_v1_CreateSignalRequest_payload_size_union {char f6[(6 #define wippersnapper_signal_v1_SignalResponse_size 2 #define wippersnapper_signal_v1_PWMRequest_size 82 #define wippersnapper_signal_v1_PWMResponse_size 11 -#define wippersnapper_signal_v1_DisplayRequest_size 1107 +#define wippersnapper_signal_v1_DisplayRequest_size 1094 #define wippersnapper_signal_v1_DisplayResponse_size 69 #ifdef __cplusplus diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index 13cbdecfd..f02a90b25 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index 166a9cff8..fb3d5dc34 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 13:28:33 2025. */ +/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From 9ca0164a954bb15272f31238209e5b83af54cd4c Mon Sep 17 00:00:00 2001 From: brentru Date: Fri, 26 Sep 2025 16:02:14 -0400 Subject: [PATCH 58/76] MagTag on Staging --- src/Wippersnapper.cpp | 2 +- src/components/display/controller.cpp | 4 +-- .../display/drivers/dispDrvSt7789.h | 29 ++++++++----------- src/components/display/hardware.cpp | 23 +++++++++++++-- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 68158a017..d8f67db57 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2915,7 +2915,7 @@ ws_status_t Wippersnapper::run() { WS.feedWDT(); // Process display controller events, if initialized - WS._displayController->update(getRSSI(), networkStatus() == WS_CONNECTED); + //WS._displayController->update(getRSSI(), networkStatus() == WS_CONNECTED); WS.feedWDT(); return WS_NET_CONNECTED; // TODO: Make this funcn void! diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 0b7349d99..47e177b59 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -69,8 +69,8 @@ bool DisplayController::Handle_Display_AddOrReplace( return false; } - WS.feedWDT(); - display->showSplash(); + //WS.feedWDT(); + //display->showSplash(); WS.feedWDT(); display->drawStatusBar(WS._config.aio_user); WS.feedWDT(); diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index 4fd6eb29d..a67ea2345 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -44,11 +44,15 @@ class dispDrvSt7789 : public dispDrvBase { int16_t rst = -1, int16_t miso = -1) : dispDrvBase(cs, dc, mosi, sck, rst, miso), _display(nullptr) {} + /*! + @brief Destructor for the ST7789 display driver. + */ ~dispDrvSt7789() { if (_display) { delete _display; _display = nullptr; } + //digitalWrite(TFT_BACKLIGHT, LOW); } /*! @@ -57,21 +61,6 @@ class dispDrvSt7789 : public dispDrvBase { */ bool begin() override { -// Special power control configuration for -// boards with built-in TFTs -#if defined(TFT_BACKLITE) - // turn on backlite - pinMode(TFT_BACKLITE, OUTPUT); - digitalWrite(TFT_BACKLITE, HIGH); - -#if defined(TFT_I2C_POWER) - // turn on the TFT / I2C power supply - pinMode(TFT_I2C_POWER, OUTPUT); - digitalWrite(TFT_I2C_POWER, HIGH); - delay(10); -#endif // TFT_I2C_POWER -#endif - _display = new Adafruit_ST7789(_pin_cs, _pin_dc, _pin_rst); if (!_display) return false; @@ -79,8 +68,14 @@ class dispDrvSt7789 : public dispDrvBase { _display->init(_width, _height); _display->setRotation(_rotation); setTextSize(ST7789_TEXT_SZ_DEFAULT); - _display->fillScreen(ST77XX_BLACK); + _display->fillScreen(ST77XX_WHITE); _display->setTextColor(ST77XX_WHITE); + +/* #ifdef TFT_BACKLIGHT + pinMode(TFT_BACKLIGHT, OUTPUT); + digitalWrite(TFT_BACKLIGHT, HIGH); // Backlight on + #endif */ + return true; } @@ -115,7 +110,7 @@ class dispDrvSt7789 : public dispDrvBase { return; } - delay(1000); + delay(1500); // Pause for 1.5 seconds } /*! diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 1f04447d3..78abd5284 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -44,12 +44,12 @@ using FnCreateDispDrvTft = std::function FactoryDrvDispTft = { - {"st7735", + {"tft-154-wide-angle", [](int16_t cs, int16_t dc, int16_t mosi, int16_t sck, int16_t rst, int16_t miso) -> dispDrvBase * { return new dispDrvSt7789(cs, dc, mosi, sck, rst, miso); }}, - {"st7789", + {"tft-154-wide-angle", [](int16_t cs, int16_t dc, int16_t mosi, int16_t sck, int16_t rst, int16_t miso) -> dispDrvBase * { return new dispDrvSt7789(cs, dc, mosi, sck, rst, miso); @@ -344,12 +344,31 @@ bool DisplayHardware::beginTft( } // Create display driver object using the factory function + WS_DEBUG_PRINTLN("[display] Creating TFT display driver with pinout: "); + WS_DEBUG_PRINT(" CS: D"); WS_DEBUG_PRINTLN(cs); + WS_DEBUG_PRINT(" DC: D"); WS_DEBUG_PRINTLN(dc); + WS_DEBUG_PRINT(" MOSI: D");WS_DEBUG_PRINTLN(mosi); + WS_DEBUG_PRINT(" SCK: D"); WS_DEBUG_PRINTLN(sck); + if (rst != -1) { + WS_DEBUG_PRINT(" RST: D"); WS_DEBUG_PRINTLN(rst); + } + if (miso != -1) { + WS_DEBUG_PRINT(" MISO: D"); WS_DEBUG_PRINTLN(miso); + } _drvDisp = CreateDrvDispTft(_name, cs, dc, mosi, sck, rst, miso); if (!_drvDisp) { WS_DEBUG_PRINTLN("[display] Failed to create display driver!"); return false; } + // Print configuration + WS_DEBUG_PRINTLN("[display] Successfully created tft display driver!"); + WS_DEBUG_PRINTLN("[display] TFT configuration:"); + WS_DEBUG_PRINT(" Width: "); WS_DEBUG_PRINTLN(config->width); + WS_DEBUG_PRINT(" Height: ");WS_DEBUG_PRINTLN(config->height); + WS_DEBUG_PRINT(" Rotation: ");WS_DEBUG_PRINTLN(config->rotation); + WS_DEBUG_PRINT(" Text Size: ");WS_DEBUG_PRINTLN(text_sz); + _drvDisp->setWidth(config->width); _drvDisp->setHeight(config->height); _drvDisp->setRotation(config->rotation); From 0e67abbedc5da7eef42148ae190299d7685af4a7 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 29 Sep 2025 12:45:58 -0400 Subject: [PATCH 59/76] Continue remove old TFT code, add status bar --- src/components/display/assets/splash.h | 1203 +++++++++-------- src/components/display/controller.cpp | 4 +- .../display/drivers/dispDrvSt7789.h | 28 +- src/provisioning/ConfigJson.cpp | 38 +- src/provisioning/ConfigJson.h | 3 - src/provisioning/tinyusb/Wippersnapper_FS.cpp | 77 -- src/provisioning/tinyusb/Wippersnapper_FS.h | 6 - 7 files changed, 621 insertions(+), 738 deletions(-) diff --git a/src/components/display/assets/splash.h b/src/components/display/assets/splash.h index a8e5b7514..69f86a9f3 100644 --- a/src/components/display/assets/splash.h +++ b/src/components/display/assets/splash.h @@ -344,607 +344,608 @@ static const unsigned char tft_bmp_logo_240135[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // 'adafruit_wippersnapper_logo', 240x240px -static const unsigned char tft_bmp_logo_240240[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf7, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, - 0xff, 0x80, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0x00, 0xf1, 0xff, 0xff, 0xb3, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x89, 0xff, - 0xff, 0x00, 0xf1, 0xff, 0xff, 0x12, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0x00, 0xf0, 0xff, 0xfc, 0x00, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x7f, - 0xfe, 0x00, 0xe0, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xfe, 0x00, 0x60, 0xff, 0xf8, 0x00, - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, - 0xfe, 0x00, 0x60, 0x7f, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, 0xfc, 0x30, 0x60, 0x7f, 0xf0, 0x00, - 0x1f, 0x00, 0xf8, 0x00, 0x07, 0xff, 0xc0, 0x00, 0x7f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, - 0xfc, 0x70, 0x00, 0x7f, 0xf0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x7f, - 0x80, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xfc, 0xc0, 0x00, 0x3f, 0xf0, 0x00, - 0x0e, 0x00, 0x70, 0x00, 0x00, 0x1f, 0x80, 0x00, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, - 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x0f, - 0x80, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, - 0x0e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x7f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, - 0xf8, 0xc0, 0x00, 0x1f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x07, - 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf0, 0x60, 0x00, 0x1f, 0xe0, 0x00, - 0x0e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, - 0xf0, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, - 0x80, 0x00, 0x00, 0x3f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xe0, 0x00, - 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x3f, 0x80, 0x01, - 0xfc, 0x01, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, - 0xe0, 0x00, 0x00, 0x0f, 0xe0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xc0, 0x03, - 0x80, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xc0, 0x00, - 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1f, 0x00, 0x1e, 0x00, 0x00, - 0x7c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, - 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, - 0x80, 0x1f, 0x00, 0x1c, 0x00, 0x00, 0x3c, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x07, 0xc0, 0x00, - 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1f, 0x00, 0x18, 0x00, 0x00, - 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, - 0x80, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, - 0x80, 0x1f, 0x00, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x80, 0x1e, 0x00, 0x10, 0x01, 0x00, - 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xc0, 0x03, - 0x80, 0x0e, 0x00, 0x10, 0x03, 0x80, 0x0c, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x30, 0x03, 0x80, - 0x0c, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, - 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0c, 0x00, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x30, 0x00, 0x00, - 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, - 0x80, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0x1f, - 0x80, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x61, 0xff, 0xff, 0x0e, 0x00, 0x00, - 0xfe, 0x00, 0x70, 0x00, 0x00, 0x3f, 0x80, 0x00, 0x01, 0xf0, 0x01, 0xff, - 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, - 0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0xff, - 0x80, 0x00, 0x07, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, - 0x7e, 0x00, 0x70, 0x00, 0x1f, 0xff, 0x80, 0x00, 0xff, 0xf0, 0x00, 0x00, - 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, - 0xff, 0xe0, 0x0f, 0xff, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xff, 0xff, - 0x80, 0x1f, 0xff, 0xf0, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x7f, 0xc0, 0x00, - 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xf8, 0x00, 0x00, - 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, - 0xe0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, - 0x80, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x03, 0xf8, 0x00, - 0x0e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xfc, 0x00, 0x00, - 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x0e, 0x00, 0x70, 0x01, 0xff, 0xff, - 0x80, 0x1f, 0xff, 0xfe, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, - 0x1e, 0x00, 0xf8, 0x03, 0xff, 0xff, 0x80, 0x1f, 0xff, 0xff, 0x80, 0x00, - 0x3c, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x1f, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, - 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, - 0x04, 0x07, 0xc0, 0x60, 0x00, 0xff, 0xc0, 0x01, 0x81, 0xe0, 0x3c, 0x00, - 0xf0, 0x00, 0x78, 0x00, 0x3c, 0x00, 0x0c, 0x00, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x7f, - 0x80, 0x01, 0x00, 0xe0, 0x7c, 0x00, 0xf0, 0x00, 0x38, 0x00, 0x1c, 0x00, - 0x0c, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, - 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0x80, 0x03, 0x00, 0xe0, 0x78, 0x00, - 0xf0, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x3f, - 0x00, 0x03, 0x00, 0x60, 0x78, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x0c, 0x00, - 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, - 0x3f, 0xf0, 0x1f, 0xf8, 0x00, 0x3f, 0x00, 0x03, 0x00, 0x60, 0x70, 0x00, - 0xf0, 0x00, 0x18, 0x00, 0x08, 0x00, 0x18, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x7f, 0x80, 0x01, 0xfe, 0x00, 0x3e, - 0x03, 0xfb, 0x00, 0x60, 0x70, 0x20, 0xe0, 0x30, 0x10, 0x18, 0x08, 0x0f, - 0xf8, 0x1c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, - 0xfc, 0x00, 0x00, 0x7f, 0x00, 0x3e, 0x00, 0x7f, 0x00, 0x00, 0x70, 0x60, - 0xe0, 0x30, 0x10, 0x18, 0x08, 0x00, 0x78, 0x1c, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x03, 0xf8, 0x00, 0x00, 0x1f, 0x80, 0x7e, - 0x00, 0x0e, 0x00, 0x00, 0xe0, 0x60, 0xe0, 0x30, 0x30, 0x38, 0x18, 0x00, - 0x78, 0x1c, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0xe0, 0x00, 0x00, 0x0f, 0xf8, 0xfe, 0x00, 0x06, 0x00, 0x00, 0xe0, 0x60, - 0xe0, 0x30, 0x30, 0x30, 0x18, 0x00, 0x78, 0x00, 0x0f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, - 0x00, 0x06, 0x00, 0x00, 0xc0, 0xe0, 0xe0, 0x00, 0x30, 0x00, 0x18, 0x00, - 0x78, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x06, 0x00, 0x00, 0xc0, 0xc0, - 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, - 0xf0, 0x06, 0x04, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x1f, - 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x06, 0x04, 0x00, 0x80, 0x00, - 0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x1f, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x30, 0x18, 0x00, 0x7f, 0xfc, - 0x00, 0x04, 0x06, 0x01, 0x80, 0x00, 0xc0, 0x07, 0xe0, 0x03, 0xf0, 0x00, - 0x70, 0x20, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x04, 0x0e, 0x01, 0x00, 0x00, - 0x40, 0xff, 0xe0, 0x7f, 0xf0, 0x00, 0x70, 0x30, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, - 0x00, 0x0c, 0x0e, 0x01, 0x00, 0x00, 0x40, 0xff, 0xe0, 0x7f, 0xe0, 0x00, - 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x00, 0x7f, 0xfc, 0x00, 0x7f, 0xfc, 0x00, 0x1c, 0x0f, 0x00, 0x03, 0xc0, - 0x00, 0xff, 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0xfc, 0x7e, 0x00, 0x7f, 0xfc, - 0x00, 0x3c, 0x0f, 0x00, 0x07, 0xc0, 0x00, 0xff, 0xc0, 0x7f, 0xe0, 0x00, - 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x01, 0xf0, 0x0f, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +const unsigned char tft_bmp_logo_240240[] PROGMEM = { + // 'adafruit_wippersnapper_logo, 240x240px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x7f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xff, 0x0e, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x76, 0x00, + 0x00, 0xff, 0x0e, 0x00, 0x00, 0xed, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xff, 0x80, 0x00, 0xff, 0x0f, 0x00, 0x03, 0xff, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x80, + 0x01, 0xff, 0x1f, 0x00, 0x03, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x01, 0xff, 0x9f, 0x00, 0x07, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, + 0x01, 0xff, 0x9f, 0x80, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x03, 0xcf, 0x9f, 0x80, 0x0f, 0xff, + 0xe0, 0xff, 0x07, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, + 0x03, 0x8f, 0xff, 0x80, 0x0f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0x80, + 0x7f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x03, 0x3f, 0xff, 0xc0, 0x0f, 0xff, + 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, + 0x07, 0x7f, 0xff, 0xc0, 0x1f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf0, + 0x7f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x07, 0x7f, 0xff, 0xc0, 0x1f, 0xff, + 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, + 0x07, 0x3f, 0xff, 0xe0, 0x1f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf8, + 0x7f, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x0f, 0x9f, 0xff, 0xe0, 0x1f, 0xff, + 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, + 0x0f, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xff, 0xfc, + 0x7f, 0xff, 0xff, 0xc0, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xf0, 0x1f, 0xff, + 0xf0, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xc0, 0x7f, 0xfe, + 0x03, 0xfe, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, + 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x3f, 0xfc, + 0x7f, 0xe1, 0xff, 0xe0, 0xff, 0xff, 0x03, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf0, 0x3f, 0xff, + 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, 0x7f, 0xe0, 0xff, 0xe1, 0xff, 0xff, + 0x83, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, + 0x1f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, + 0x7f, 0xe0, 0xff, 0xe3, 0xff, 0xff, 0xc3, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, + 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, 0x7f, 0xe0, 0xff, 0xe7, 0xff, 0xff, + 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfc, + 0x7f, 0xff, 0xff, 0xfc, 0x3f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, + 0x7f, 0xe0, 0xff, 0xe7, 0xff, 0xff, 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, 0x7f, 0xe1, 0xff, 0xef, 0xfe, 0xff, + 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0x8f, 0xfe, 0x3f, 0xfc, + 0x7f, 0xf1, 0xff, 0xef, 0xfc, 0x7f, 0xf3, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc1, 0xff, 0x8f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xcf, 0xfc, 0x7f, + 0xf3, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0x8f, 0xff, 0xff, 0xfc, + 0x7f, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xf3, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x81, 0xff, 0x8f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xcf, 0xff, 0xff, + 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0x8f, 0xff, 0xff, 0xf8, + 0x7f, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x81, 0xff, 0x8f, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0x8f, 0xff, 0xff, + 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x8f, 0xff, 0xff, 0xe0, + 0x7f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x9e, 0x00, 0x00, 0xf1, 0xff, 0xff, + 0x01, 0xff, 0x8f, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xfe, 0x0f, 0xfe, 0x00, + 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x80, 0x00, 0x00, 0x01, 0xff, 0xff, 0x01, 0xff, 0x8f, 0xff, 0xff, 0x00, + 0x7f, 0xff, 0xf8, 0x0f, 0xfe, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, + 0x81, 0xff, 0x8f, 0xff, 0xe0, 0x00, 0x7f, 0xff, 0x00, 0x0f, 0xff, 0xff, + 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xfe, + 0x00, 0x1f, 0xf0, 0x00, 0xff, 0xff, 0xc1, 0xff, 0x8f, 0xfe, 0x00, 0x00, + 0x7f, 0xe0, 0x00, 0x0f, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0xff, 0xf8, 0x03, 0xff, 0xff, 0x80, 0x3f, 0xff, + 0xe1, 0xff, 0x8f, 0xfe, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x07, 0xff, 0xff, + 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, + 0x1f, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x00, 0x00, + 0x7f, 0xe0, 0x00, 0x07, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x7f, 0xff, 0xff, 0xfc, 0x07, 0xff, + 0xf1, 0xff, 0x8f, 0xfe, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x03, 0xff, 0xff, + 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x01, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xf1, 0xff, 0x8f, 0xfe, 0x00, 0x00, + 0x7f, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x07, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xff, + 0xe1, 0xff, 0x07, 0xfc, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x7f, 0xff, + 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x03, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, + 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, + 0xfb, 0xf8, 0x3f, 0x9f, 0xff, 0x00, 0x3f, 0xfe, 0x7e, 0x1f, 0xc3, 0xff, + 0x0f, 0xff, 0x87, 0xff, 0xc3, 0xff, 0xf3, 0xff, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x00, 0x1f, 0xff, 0x80, + 0x7f, 0xfe, 0xff, 0x1f, 0x83, 0xff, 0x0f, 0xff, 0xc7, 0xff, 0xe3, 0xff, + 0xf3, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, + 0xf0, 0x00, 0x00, 0x1f, 0xff, 0xc0, 0x7f, 0xfc, 0xff, 0x1f, 0x87, 0xff, + 0x0f, 0xff, 0xc7, 0xff, 0xe3, 0xff, 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xc0, + 0xff, 0xfc, 0xff, 0x9f, 0x87, 0xff, 0x0f, 0xff, 0xe7, 0xff, 0xf3, 0xff, + 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, + 0xc0, 0x0f, 0xe0, 0x07, 0xff, 0xc0, 0xff, 0xfc, 0xff, 0x9f, 0x8f, 0xff, + 0x0f, 0xff, 0xe7, 0xff, 0xf7, 0xff, 0xe7, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x80, 0x7f, 0xfe, 0x01, 0xff, 0xc1, + 0xfc, 0x04, 0xff, 0x9f, 0x8f, 0xdf, 0x1f, 0xcf, 0xef, 0xe7, 0xf7, 0xf0, + 0x07, 0xe3, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, + 0x03, 0xff, 0xff, 0x80, 0xff, 0xc1, 0xff, 0x80, 0xff, 0xff, 0x8f, 0x9f, + 0x1f, 0xcf, 0xef, 0xe7, 0xf7, 0xff, 0x87, 0xe3, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x07, 0xff, 0xff, 0xe0, 0x7f, 0x81, + 0xff, 0xf1, 0xff, 0xff, 0x1f, 0x9f, 0x1f, 0xcf, 0xcf, 0xc7, 0xe7, 0xff, + 0x87, 0xe3, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x1f, 0xff, 0xff, 0xf0, 0x07, 0x01, 0xff, 0xf9, 0xff, 0xff, 0x1f, 0x9f, + 0x1f, 0xcf, 0xcf, 0xcf, 0xe7, 0xff, 0x87, 0xff, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x00, + 0xff, 0xf9, 0xff, 0xff, 0x3f, 0x1f, 0x1f, 0xff, 0xcf, 0xff, 0xe7, 0xff, + 0x87, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x7f, 0xf9, 0xff, 0xff, 0x3f, 0x3f, + 0x3f, 0xff, 0x9f, 0xff, 0xcf, 0xff, 0x0f, 0xff, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, + 0x0f, 0xf9, 0xfb, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x9f, 0xff, 0xcf, 0xe0, + 0x0f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0xf9, 0xfb, 0xff, 0x7f, 0xff, + 0x3f, 0xff, 0x1f, 0xff, 0x0f, 0xe0, 0x0f, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xcf, 0xe7, 0xff, 0x80, 0x03, + 0xff, 0xfb, 0xf9, 0xfe, 0x7f, 0xff, 0x3f, 0xf8, 0x1f, 0xfc, 0x0f, 0xff, + 0x8f, 0xdf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xff, 0xc0, 0x07, 0xff, 0x80, 0x03, 0xff, 0xfb, 0xf1, 0xfe, 0xff, 0xff, + 0xbf, 0x00, 0x1f, 0x80, 0x0f, 0xff, 0x8f, 0xcf, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xc0, 0x07, 0xff, 0x80, 0x03, + 0xff, 0xf3, 0xf1, 0xfe, 0xff, 0xff, 0xbf, 0x00, 0x1f, 0x80, 0x1f, 0xff, + 0x9f, 0xcf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xff, 0x80, 0x03, 0xff, 0x80, 0x03, 0xff, 0xe3, 0xf0, 0xff, 0xfc, 0x3f, + 0xff, 0x00, 0x3f, 0x80, 0x1f, 0xff, 0x9f, 0xcf, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x03, 0x81, 0xff, 0x80, 0x03, + 0xff, 0xc3, 0xf0, 0xff, 0xf8, 0x3f, 0xff, 0x00, 0x3f, 0x80, 0x1f, 0xff, + 0x9f, 0xcf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x0f, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 'adafruit_wippersnapper_logo', ePD Magtag, 296x128px static const unsigned char epd_bitmap_ws_logo_296128[] = { diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 47e177b59..0b7349d99 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -69,8 +69,8 @@ bool DisplayController::Handle_Display_AddOrReplace( return false; } - //WS.feedWDT(); - //display->showSplash(); + WS.feedWDT(); + display->showSplash(); WS.feedWDT(); display->drawStatusBar(WS._config.aio_user); WS.feedWDT(); diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index a67ea2345..46277c263 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -52,7 +52,9 @@ class dispDrvSt7789 : public dispDrvBase { delete _display; _display = nullptr; } - //digitalWrite(TFT_BACKLIGHT, LOW); +#if defined(ARDUINO_FUNHOUSE_ESP32S2) + digitalWrite(TFT_BACKLIGHT, LOW); +#endif } /*! @@ -68,13 +70,14 @@ class dispDrvSt7789 : public dispDrvBase { _display->init(_width, _height); _display->setRotation(_rotation); setTextSize(ST7789_TEXT_SZ_DEFAULT); - _display->fillScreen(ST77XX_WHITE); + _display->fillScreen(ST77XX_BLACK); _display->setTextColor(ST77XX_WHITE); -/* #ifdef TFT_BACKLIGHT +#if defined(ARDUINO_FUNHOUSE_ESP32S2) + // Turn backlight on pinMode(TFT_BACKLIGHT, OUTPUT); - digitalWrite(TFT_BACKLIGHT, HIGH); // Backlight on - #endif */ + digitalWrite(TFT_BACKLIGHT, HIGH); +#endif return true; } @@ -102,7 +105,7 @@ class dispDrvSt7789 : public dispDrvBase { // Display the appropriate splash screen based on resolution if (_width == 240 && _height == 240) { - _display->drawBitmap(0, 0, tft_bmp_logo_240240, 240, 240, ST77XX_BLACK); + _display->drawBitmap(0, 0, tft_bmp_logo_240240, 240, 240, ST77XX_WHITE); } else if (_width == 240 && _height == 135) { _display->drawBitmap(0, 0, tft_bmp_logo_240135, 240, 135, EPD_BLACK); } else { @@ -110,7 +113,7 @@ class dispDrvSt7789 : public dispDrvBase { return; } - delay(1500); // Pause for 1.5 seconds + delay(1000); } /*! @@ -141,10 +144,8 @@ class dispDrvSt7789 : public dispDrvBase { _display->fillScreen(ST77XX_BLACK); // Draw status bar - // TODO: We are not drawing a border here because it isnt - // required on a color display, I think. _display->fillRect(0, 0, _display->width(), _status_bar_height, - ST77XX_BLACK); + ST77XX_WHITE); // Draw username on left side of the status bar _display->setTextSize(1); @@ -202,8 +203,11 @@ class dispDrvSt7789 : public dispDrvBase { if (_display == nullptr) return; - // Start with a fresh display buffer - _display->fillScreen(ST77XX_BLACK); + _display->setTextColor(ST77XX_WHITE); + + // Clear only the area below the status bar + _display->fillRect(0, _status_bar_height, _width, + _height - _status_bar_height, ST77XX_BLACK); int16_t y_idx = _status_bar_height; _display->setCursor(0, y_idx); diff --git a/src/provisioning/ConfigJson.cpp b/src/provisioning/ConfigJson.cpp index 00c12a33a..36dccb5fb 100644 --- a/src/provisioning/ConfigJson.cpp +++ b/src/provisioning/ConfigJson.cpp @@ -47,40 +47,4 @@ void convertFromJson(JsonVariantConst src, secretsConfig &dst) { dst.status_pixel_brightness = src["status_pixel_brightness"] | 0.2; // Parse MQTT port from secrets, if exists dst.io_port = src["io_port"] | 8883; -} - -// Converts a displayConfigSPI structure to a JSON variant -void convertToJson(const displayConfigSPI &src, JsonVariant dst) { - dst["pin_cs"] = src.pinCs; - dst["pin_dc"] = src.pinDc; - dst["pin_mosi"] = src.pinMosi; - dst["pin_sck"] = src.pinSck; - dst["pin_rst"] = src.pinRst; -} - -// Extracts a displayConfigSPI structure from a JSON variant -void convertFromJson(JsonVariantConst src, displayConfigSPI &dst) { - dst.pinCs = src["pin_cs"] | 40; - dst.pinDc = src["pin_dc"] | 39; - dst.pinMosi = src["pin_mosi"] | 0; - dst.pinSck = src["pin_sck"] | 0; - dst.pinRst = src["pin_rst"] | 41; -} - -// Converts a displayConfig structure to a JSON variant -void convertToJson(const displayConfig &src, JsonVariant dst) { - dst["driver"] = src.driver; - dst["width"] = src.width; - dst["height"] = src.height; - dst["rotation"] = src.rotation; - dst["spi_config"] = src.spiConfig; -} - -// Extracts a displayConfig structure from a JSON variant -void convertFromJson(JsonVariantConst src, displayConfig &dst) { - strlcpy(dst.driver, src["driver"] | "ST7789", sizeof(dst.driver)); - dst.width = src["width"] | 128; - dst.height = src["height"] | 64; - dst.rotation = src["rotation"] | 0; - dst.spiConfig = src["spi_config"]; -} +} \ No newline at end of file diff --git a/src/provisioning/ConfigJson.h b/src/provisioning/ConfigJson.h index 990aba9d6..38871cc65 100644 --- a/src/provisioning/ConfigJson.h +++ b/src/provisioning/ConfigJson.h @@ -25,7 +25,4 @@ void convertFromJson(JsonVariantConst src, networkConfig &dst); // Converters for secrets configuration void convertToJson(const secretsConfig &src, JsonVariant dst); void convertFromJson(JsonVariantConst src, secretsConfig &dst); -// Converters for display configuration -void convertToJson(const displayConfig &src, JsonVariant dst); -void convertFromJson(JsonVariantConst src, displayConfig &dst); #endif // CONFIGJSON_H \ No newline at end of file diff --git a/src/provisioning/tinyusb/Wippersnapper_FS.cpp b/src/provisioning/tinyusb/Wippersnapper_FS.cpp index 355119fa1..eef798d12 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.cpp +++ b/src/provisioning/tinyusb/Wippersnapper_FS.cpp @@ -496,83 +496,6 @@ void Wippersnapper_FS::fsHalt(String msg) { } } -#ifdef ARDUINO_FUNHOUSE_ESP32S2 -void Wippersnapper_FS::createDisplayConfig() { - // Open file for writing - File32 displayFile = wipperFatFs.open("/display_config.json", FILE_WRITE); - - // Create a default displayConfig structure - displayConfig displayConfig; - strcpy(displayConfig.driver, "ST7789"); - displayConfig.width = 240; - displayConfig.height = 240; - displayConfig.rotation = 0; - displayConfig.spiConfig.pinCs = 40; - displayConfig.spiConfig.pinDc = 39; - displayConfig.spiConfig.pinMosi = 0; - displayConfig.spiConfig.pinSck = 0; - displayConfig.spiConfig.pinRst = 41; - - // Create and fill JSON document from displayConfig - JsonDocument doc; - if (!doc.set(displayConfig)) { - fsHalt("ERROR: Unable to set displayConfig, no space in arduinoJSON " - "document!"); - } - // Write the file out to the filesystem - serializeJsonPretty(doc, displayFile); - displayFile.flush(); - displayFile.close(); - delay(2500); // give FS some time to write the file -} - -bool Wippersnapper_FS::parseDisplayConfig(displayConfig &dispCfg, bool force_recreate) { - if (force_recreate) { - if (wipperFatFs.exists("/display_config.json")) { - wipperFatFs.remove("/display_config.json"); - } -#ifdef ARDUINO_FUNHOUSE_ESP32S2 - createDisplayConfig(); -#endif - } - - // Check if display_config.json file exists, if not, generate it - if (!wipperFatFs.exists("/display_config.json")) { - WS_DEBUG_PRINTLN("Could not find display_config.json, generating..."); -#ifdef ARDUINO_FUNHOUSE_ESP32S2 - createDisplayConfig(); // generate a default display_config.json for - // FunHouse -#endif - } - - // Attempt to open file for JSON parsing - File32 file = wipperFatFs.open("/display_config.json", FILE_READ); - if (!file) { - if (!force_recreate) { - return false; - } - fsHalt("FATAL ERROR: Unable to open display_config.json for parsing"); - } - - // Attempt to deserialize the file's json document - JsonDocument doc; - DeserializationError error = deserializeJson(doc, file); - if (error) { - if (!force_recreate) { - return false; - } - fsHalt(String("FATAL ERROR: Unable to parse display_config.json - " - "deserializeJson() failed with code") + - error.c_str()); - } - // Close the file, we're done with it - file.close(); - // Extract a displayConfig struct from the JSON document - dispCfg = doc.as(); - return true; -} -#endif // ARDUINO_FUNHOUSE_ESP32S2 - /**************************************************************************/ /*! @brief Callback invoked when received READ10 command. Copies disk's diff --git a/src/provisioning/tinyusb/Wippersnapper_FS.h b/src/provisioning/tinyusb/Wippersnapper_FS.h index 34263d009..7068cd691 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.h +++ b/src/provisioning/tinyusb/Wippersnapper_FS.h @@ -26,7 +26,6 @@ // forward decl. class Wippersnapper; -struct displayConfig; // global TinyUSB callbacks int32_t qspi_msc_write_cb(uint32_t lba, uint8_t *buffer, uint32_t bufsize); @@ -57,11 +56,6 @@ class Wippersnapper_FS { void fsHalt(String msg); void parseSecrets(); - -#ifdef ARDUINO_FUNHOUSE_ESP32S2 - bool parseDisplayConfig(displayConfig &displayFile, bool force_recreate = false); - void createDisplayConfig(); -#endif private: bool _freshFS = false; /*!< True if filesystem was initialized by WipperSnapper, False otherwise. */ From cc485856721a684b599b1a2856c8739512b5ab90 Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 1 Oct 2025 13:25:13 -0400 Subject: [PATCH 60/76] Pull status bar into controller, support on ST79x --- src/Wippersnapper.cpp | 25 +++++----- src/Wippersnapper_demo.ino.cpp | 26 ++++++++++ src/components/display/controller.cpp | 38 +++++++++++++-- src/components/display/controller.h | 4 ++ src/components/display/drivers/dispDrvBase.h | 4 -- .../display/drivers/dispDrvSt7789.h | 48 ++++++++++++++++--- .../dispDrvThinkInkGrayscale4Eaamfgn.h | 7 +-- src/components/display/hardware.cpp | 32 +------------ src/components/i2c/WipperSnapper_I2C.cpp | 3 ++ 9 files changed, 125 insertions(+), 62 deletions(-) create mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index d8f67db57..5598963e2 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -423,7 +423,7 @@ bool cbSignalMsg(pb_istream_t *stream, const pb_field_t *field, void **arg) { is_success = false; WS.pinCfgCompleted = false; } - // If this is the initial configuration + // Is this the initial configuration? if (!WS.pinCfgCompleted) { WS_DEBUG_PRINTLN("Initial Pin Configuration Complete!"); WS.pinCfgCompleted = true; @@ -520,10 +520,10 @@ void publishI2CResponse(wippersnapper_signal_v1_I2CResponse *msgi2cResponse) { size_t msgSz; pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_I2CResponse_fields, msgi2cResponse); - WS_DEBUG_PRINT("Publishing Message: I2CResponse..."); + WS_DEBUG_PRINTLN("Publishing Message: I2CResponse..."); if (!WS._mqtt->publish(WS._topic_signal_i2c_device, WS._buffer_outgoing, - msgSz, 1)) { - WS_DEBUG_PRINTLN("ERROR: Failed to publish I2C Response!"); + msgSz, 0)) { + WS_DEBUG_PRINTLN("\tERROR: Failed to publish I2C Response!"); } else { WS_DEBUG_PRINTLN("Published!"); } @@ -1579,10 +1579,10 @@ bool cbDecodeDisplayMsg(pb_istream_t *stream, const pb_field_t *field, size_t msgSz; pb_get_encoded_size(&msgSz, wippersnapper_signal_v1_DisplayResponse_fields, &msgResp); - WS_DEBUG_PRINT("Publishing DisplayResponse Message..."); + WS_DEBUG_PRINTLN("Publishing DisplayResponse Message..."); if (!WS._mqtt->publish(WS._topic_signal_display_device, WS._buffer_outgoing, - msgSz, 1)) { - WS_DEBUG_PRINTLN("ERROR: Failed to DisplayResponse Response!"); + msgSz, 0)) { + WS_DEBUG_PRINTLN("ERROR: Failed to Publish DisplayResponse!"); } else { WS_DEBUG_PRINTLN("Published!"); } @@ -2826,7 +2826,6 @@ void Wippersnapper::connect() { WS._analogIO = new Wippersnapper_AnalogIO(5, 3.3); // Configure hardware - // WS.pinCfgCompleted = true; while (!WS.pinCfgCompleted) { WS_DEBUG_PRINTLN( "Polling for message containing hardware configuration..."); @@ -2873,8 +2872,12 @@ void Wippersnapper::publishPinConfigComplete() { // Publish message WS_DEBUG_PRINTLN("Publishing to pin config complete..."); - WS.publish(WS._topic_device_pin_config_complete, _message_buffer, - _message_len, 1); + if (!WS._mqtt->publish(WS._topic_device_pin_config_complete, _message_buffer, + _message_len, 0)) { + WS_DEBUG_PRINTLN("Failed to publish pin config complete message!"); + } else { + WS_DEBUG_PRINTLN("Published pin config complete message!"); + } } /**************************************************************************/ @@ -2915,7 +2918,7 @@ ws_status_t Wippersnapper::run() { WS.feedWDT(); // Process display controller events, if initialized - //WS._displayController->update(getRSSI(), networkStatus() == WS_CONNECTED); + WS._displayController->update(getRSSI(), networkStatus() == WS_CONNECTED); WS.feedWDT(); return WS_NET_CONNECTED; // TODO: Make this funcn void! diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp new file mode 100644 index 000000000..f2bce77a7 --- /dev/null +++ b/src/Wippersnapper_demo.ino.cpp @@ -0,0 +1,26 @@ +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpx8r34gur" +#include +# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +#include "Wippersnapper_Networking.h" +Wippersnapper_WiFi wipper; + + +#define WS_DEBUG +void setup(); +void loop(); +#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +void setup() { + + wipper.provision(); + + Serial.begin(115200); + + + wipper.connect(); + +} + +void loop() { + wipper.run(); +} \ No newline at end of file diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 0b7349d99..b1f9479a1 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -17,7 +17,9 @@ /*! @brief Constructs a new DisplayController object */ -DisplayController::DisplayController() {} +DisplayController::DisplayController() { + _last_bar_update = 0; +} /*! @brief Destructor @@ -77,6 +79,8 @@ bool DisplayController::Handle_Display_AddOrReplace( _hw_instances.push_back(display); // Store the display instance WS_DEBUG_PRINTLN("[display] Display added or replaced successfully!"); + WS.feedWDT(); + WS.runNetFSM(); return true; } @@ -128,19 +132,47 @@ bool DisplayController::Handle_Display_Write( WS_DEBUG_PRINT("[display] Writing message to display: "); WS_DEBUG_PRINTLN(msgWrite->message); display->writeMessage(msgWrite->message); + WS.feedWDT(); + WS.runNetFSM(); return true; } +/*! + @brief Updates the status bar on all managed displays. + @param rssi + The current WiFi RSSI value. + @param is_connected + The current MQTT connection status. +*/ void DisplayController::update(int32_t rssi, bool is_connected) { // if _hw_instances is empty, early out if (_hw_instances.size() == 0) return; + // Only update the status bar every 60 seconds + unsigned long now = millis(); + if (now - _last_bar_update < 60000) + return; + _last_bar_update = now; + + // Early-out if nothing has changed + // and only consider WiFi changes +/-3dB + bool rssi_changed = abs(rssi - _statusbar_rssi) >= 3; + if (!rssi_changed && is_connected == _statusbar_mqtt_connected && 100 == _statusbar_bat) { + return; + } + // Get the driver instance for the display - DisplayHardware *display = nullptr; - for (auto &hw_instance : _hw_instances) { + for (DisplayHardware *hw_instance : _hw_instances) { // Note: For now, battery is always 100% as we don't have a way to read it // yet. hw_instance->updateStatusBar(rssi, 100, is_connected); } + + // Update the cached status bar values + _statusbar_rssi = rssi; + _statusbar_mqtt_connected = is_connected; + _statusbar_bat = 100; // NOTE: Always 100%, for now + WS.feedWDT(); + WS.runNetFSM(); } \ No newline at end of file diff --git a/src/components/display/controller.h b/src/components/display/controller.h index eff8e38fa..eeffadfd8 100644 --- a/src/components/display/controller.h +++ b/src/components/display/controller.h @@ -40,6 +40,10 @@ class DisplayController { private: std::vector _hw_instances; ///< Holds pointers to DisplayHardware instances + int8_t _statusbar_rssi; ///< RSSI value for status bar + uint8_t _statusbar_bat; ///< Battery level, as a percentage, for the status bar + bool _statusbar_mqtt_connected; ///< MQTT connection status for the status bar + unsigned long _last_bar_update; ///< Timestamp of last status bar update }; extern Wippersnapper Ws; ///< Global WS instance #endif \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index 906494d21..8c71ed07b 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -175,10 +175,6 @@ class dispDrvBase { int16_t _height; ///< Height of the display int16_t _width; ///< Width of the display uint8_t _rotation; ///< Rotation of the display - int8_t _statusbar_rssi; ///< RSSI value for status bar - uint8_t - _statusbar_bat; ///< Battery level, as a percentage, for the status bar - bool _statusbar_mqtt_connected; ///< MQTT connection status for the status bar }; #endif // WS_DISP_DRV_BASE_H \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index 46277c263..d819b6f49 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -107,13 +107,13 @@ class dispDrvSt7789 : public dispDrvBase { if (_width == 240 && _height == 240) { _display->drawBitmap(0, 0, tft_bmp_logo_240240, 240, 240, ST77XX_WHITE); } else if (_width == 240 && _height == 135) { - _display->drawBitmap(0, 0, tft_bmp_logo_240135, 240, 135, EPD_BLACK); + _display->drawBitmap(0, 0, tft_bmp_logo_240135, 240, 135, ST77XX_BLACK); } else { // Unsupported resolution return; } - delay(1000); + delay(500); } /*! @@ -149,7 +149,7 @@ class dispDrvSt7789 : public dispDrvBase { // Draw username on left side of the status bar _display->setTextSize(1); - _display->setTextColor(EPD_BLACK); + _display->setTextColor(ST77XX_BLACK); _display->setCursor(5, 6); _display->print(io_username); @@ -162,11 +162,11 @@ class dispDrvSt7789 : public dispDrvBase { if (_height == 240) { // Draw 16px icons on right side of the status bar _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, - _status_bar_icon_sz, _status_bar_icon_sz, EPD_BLACK); + _status_bar_icon_sz, _status_bar_icon_sz, ST77XX_BLACK); _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_full, _status_bar_icon_sz, - _status_bar_icon_sz, EPD_BLACK); + _status_bar_icon_sz, ST77XX_BLACK); _display->drawBitmap(batteryX, iconY, epd_bmp_bat_full, - _status_bar_icon_sz, _status_bar_icon_sz, EPD_BLACK); + _status_bar_icon_sz, _status_bar_icon_sz, ST77XX_BLACK); } else if (_height == 135) { // TODO: Draw 12px icons on right side of the status bar } else { @@ -189,7 +189,41 @@ class dispDrvSt7789 : public dispDrvBase { if (!_display) return; - // TODO - needs to be implemented! + WS_DEBUG_PRINTLN("Updating ST7789 status bar"); + + int iconY = (_status_bar_height - _status_bar_icon_sz) / 2; + int batteryX = _display->width() - _status_bar_icon_sz - _status_bar_icon_margin; + int wifiX = batteryX - _status_bar_icon_sz - _status_bar_icon_spacing; + int cloudX = wifiX - _status_bar_icon_sz - _status_bar_icon_spacing; + + // Clear and draw the new cloud icon, based on MQTT connection status + _display->fillRect(cloudX, iconY, _status_bar_icon_sz, _status_bar_icon_sz, + ST77XX_WHITE); + if (mqtt_status == 21) { + _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, + _status_bar_icon_sz, _status_bar_icon_sz, ST77XX_BLACK); + } else { + _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_offline, + _status_bar_icon_sz, _status_bar_icon_sz, ST77XX_BLACK); + } + + // Update WiFi icon only if RSSI has changed significantly (+/-3dB) + const unsigned char* wifi_icon = epd_bmp_wifi_no_signal; + if (rssi >= -50) { + wifi_icon = epd_bmp_wifi_full; + } else if (rssi < -50 && rssi >= -60) { + wifi_icon = epd_bmp_wifi_fair; + } else if (rssi < -60 && rssi >= -70) { + wifi_icon = epd_bmp_wifi_weak; + } else if (rssi < -70 && rssi >= -80) { + wifi_icon = epd_bmp_wifi_no_signal; + } else { + wifi_icon = epd_bmp_wifi_no_signal; + } + // Clear and draw the new WiFi icon, based on RSSI + _display->fillRect(wifiX, iconY, _status_bar_icon_sz, _status_bar_icon_sz, + ST77XX_WHITE); + _display->drawBitmap(wifiX, iconY, wifi_icon, _status_bar_icon_sz, _status_bar_icon_sz, ST77XX_BLACK); } /*! diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index c5c7d2f55..8a8e96c1b 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -152,7 +152,6 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { // For EPD - redraws take 1-2 seconds, so only update the cloud state // Update cloud icon only if it changed state - if (mqtt_status != _statusbar_mqtt_connected) { int iconSpacing = 4; int rightMargin = 5; int iconY = @@ -173,12 +172,8 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_offline, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); } - _statusbar_mqtt_connected = mqtt_status; - do_update = true; - } - if (do_update) - _display->display(); + _display->display(); } /*! diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 78abd5284..7dbb1a5b2 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -329,46 +329,16 @@ bool DisplayHardware::beginTft( miso = parsePin(spi_config->pin_miso); } - // Configure text size based on suffix in driver name + // TODO: Implement Text_size based on future Protobuf that includes it uint8_t text_sz; // Default text size - if (strstr(_name, "-lg") != nullptr) { - // Larger text size for displays with -lg suffix - text_sz = 4; - removeSuffix("-lg"); - } else if (strstr(_name, "-md") != nullptr) { - // Larger text size for displays with -md suffix - text_sz = 3; - removeSuffix("-md"); - } else { - text_sz = 1; - } // Create display driver object using the factory function - WS_DEBUG_PRINTLN("[display] Creating TFT display driver with pinout: "); - WS_DEBUG_PRINT(" CS: D"); WS_DEBUG_PRINTLN(cs); - WS_DEBUG_PRINT(" DC: D"); WS_DEBUG_PRINTLN(dc); - WS_DEBUG_PRINT(" MOSI: D");WS_DEBUG_PRINTLN(mosi); - WS_DEBUG_PRINT(" SCK: D"); WS_DEBUG_PRINTLN(sck); - if (rst != -1) { - WS_DEBUG_PRINT(" RST: D"); WS_DEBUG_PRINTLN(rst); - } - if (miso != -1) { - WS_DEBUG_PRINT(" MISO: D"); WS_DEBUG_PRINTLN(miso); - } _drvDisp = CreateDrvDispTft(_name, cs, dc, mosi, sck, rst, miso); if (!_drvDisp) { WS_DEBUG_PRINTLN("[display] Failed to create display driver!"); return false; } - // Print configuration - WS_DEBUG_PRINTLN("[display] Successfully created tft display driver!"); - WS_DEBUG_PRINTLN("[display] TFT configuration:"); - WS_DEBUG_PRINT(" Width: "); WS_DEBUG_PRINTLN(config->width); - WS_DEBUG_PRINT(" Height: ");WS_DEBUG_PRINTLN(config->height); - WS_DEBUG_PRINT(" Rotation: ");WS_DEBUG_PRINTLN(config->rotation); - WS_DEBUG_PRINT(" Text Size: ");WS_DEBUG_PRINTLN(text_sz); - _drvDisp->setWidth(config->width); _drvDisp->setHeight(config->height); _drvDisp->setRotation(config->rotation); diff --git a/src/components/i2c/WipperSnapper_I2C.cpp b/src/components/i2c/WipperSnapper_I2C.cpp index 2947702c2..fa4db47dd 100644 --- a/src/components/i2c/WipperSnapper_I2C.cpp +++ b/src/components/i2c/WipperSnapper_I2C.cpp @@ -103,6 +103,8 @@ WipperSnapper_Component_I2C::WipperSnapper_Component_I2C( _portNum = msgInitRequest->i2c_port_number; _busStatusResponse = wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_SUCCESS; } + + WS.runNetFSM(); } /*************************************************************/ @@ -1067,6 +1069,7 @@ void WipperSnapper_Component_I2C::updateI2CDeviceProperties( // set response OK _busStatusResponse = wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_SUCCESS; + WS.runNetFSM(); } /*******************************************************************************/ From 74659486c5c37d1df9fc00b86a4ca6d3c9aac2f8 Mon Sep 17 00:00:00 2001 From: brentru Date: Wed, 1 Oct 2025 14:06:43 -0400 Subject: [PATCH 61/76] Fix: St7789 Message Height --- src/Wippersnapper.cpp | 2 +- src/Wippersnapper_demo.ino.cpp | 26 ------------------- .../display/drivers/dispDrvSt7789.h | 6 +++-- 3 files changed, 5 insertions(+), 29 deletions(-) delete mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 5598963e2..2815f2ef4 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2918,7 +2918,7 @@ ws_status_t Wippersnapper::run() { WS.feedWDT(); // Process display controller events, if initialized - WS._displayController->update(getRSSI(), networkStatus() == WS_CONNECTED); + WS._displayController->update(getRSSI(), WS._mqtt->connected()); WS.feedWDT(); return WS_NET_CONNECTED; // TODO: Make this funcn void! diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp deleted file mode 100644 index f2bce77a7..000000000 --- a/src/Wippersnapper_demo.ino.cpp +++ /dev/null @@ -1,26 +0,0 @@ -# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpx8r34gur" -#include -# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -#include "Wippersnapper_Networking.h" -Wippersnapper_WiFi wipper; - - -#define WS_DEBUG -void setup(); -void loop(); -#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -void setup() { - - wipper.provision(); - - Serial.begin(115200); - - - wipper.connect(); - -} - -void loop() { - wipper.run(); -} \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index d819b6f49..5d5eedd4c 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -199,7 +199,7 @@ class dispDrvSt7789 : public dispDrvBase { // Clear and draw the new cloud icon, based on MQTT connection status _display->fillRect(cloudX, iconY, _status_bar_icon_sz, _status_bar_icon_sz, ST77XX_WHITE); - if (mqtt_status == 21) { + if (mqtt_status) { _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, _status_bar_icon_sz, _status_bar_icon_sz, ST77XX_BLACK); } else { @@ -243,13 +243,15 @@ class dispDrvSt7789 : public dispDrvBase { _display->fillRect(0, _status_bar_height, _width, _height - _status_bar_height, ST77XX_BLACK); int16_t y_idx = _status_bar_height; - _display->setCursor(0, y_idx); // Calculate the line height based on the text size (NOTE: base height is // 8px) int16_t line_height = 8 * _text_sz; uint16_t c_idx = 0; size_t msg_size = strlen(message); + // Begin with a small offset from status bar + y_idx += 5; + _display->setCursor(0, y_idx); for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) { if (y_idx + line_height > _height) break; From 6e5e4bcc8769c7401716e9cab6f0d9d8f6f847d5 Mon Sep 17 00:00:00 2001 From: brentru Date: Thu, 2 Oct 2025 12:03:10 -0400 Subject: [PATCH 62/76] Fix: Move status bar state to drvBase/drivers, 240x135 logo showing up --- src/components/display/assets/splash.h | 597 ++++++++---------- src/components/display/controller.cpp | 11 - src/components/display/controller.h | 3 - src/components/display/drivers/dispDrvBase.h | 8 + .../display/drivers/dispDrvSt7789.h | 161 ++--- .../dispDrvThinkInkGrayscale4Eaamfgn.h | 38 +- src/components/display/hardware.cpp | 8 +- 7 files changed, 367 insertions(+), 459 deletions(-) diff --git a/src/components/display/assets/splash.h b/src/components/display/assets/splash.h index 69f86a9f3..57c5edb39 100644 --- a/src/components/display/assets/splash.h +++ b/src/components/display/assets/splash.h @@ -2,346 +2,263 @@ #define _SPLASH_H_ #include -// 'adafruit_wippersnapper_logo', 240x135px -static const unsigned char tft_bmp_logo_240135[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xf7, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, - 0xff, 0x80, 0xf3, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xdb, 0xff, 0xff, 0x00, 0xf1, 0xff, 0xff, 0xb3, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xc1, 0x7f, - 0xff, 0x00, 0xf1, 0xff, 0xfd, 0x32, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x00, 0x7f, 0xff, 0x00, 0xf1, 0xff, 0xfd, 0x00, - 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0x00, 0x7f, - 0xfe, 0x00, 0xe0, 0xff, 0xfc, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, 0xfe, 0x00, 0x60, 0xff, 0xf8, 0x00, - 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x3f, - 0xfc, 0x00, 0x60, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, 0xfc, 0x30, 0x60, 0x7f, 0xf0, 0x00, - 0x1e, 0x00, 0xf8, 0x00, 0x03, 0xff, 0xc0, 0x00, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x1f, - 0xfc, 0x70, 0x00, 0x7f, 0xf0, 0x00, 0x1e, 0x00, 0x70, 0x00, 0x00, 0x7f, - 0x80, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xfc, 0xc0, 0x00, 0x3f, 0xe0, 0x00, - 0x0e, 0x00, 0x70, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, - 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x0f, - 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf8, 0x80, 0x00, 0x3f, 0xe0, 0x00, - 0x0e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, - 0xf8, 0xc0, 0x00, 0x1f, 0xe0, 0x00, 0x0e, 0x00, 0x70, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, 0xf0, 0x60, 0x00, 0x1f, 0xe0, 0x00, - 0x0e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0x0f, - 0xf0, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x0f, 0xff, 0xf0, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x0f, 0xe0, 0x00, - 0x1f, 0xff, 0xf0, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x1f, 0x80, 0x01, - 0xfc, 0x01, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, - 0xf0, 0x00, 0x00, 0x0f, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xc0, 0x03, - 0x00, 0x1e, 0x00, 0x1f, 0x00, 0x00, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xe0, 0x00, 0x00, 0x0f, 0xc0, 0x00, - 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x00, - 0x7c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, - 0xe0, 0x00, 0x00, 0x07, 0xc0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, - 0x00, 0x1f, 0x00, 0x1c, 0x00, 0x00, 0x3c, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x00, 0x07, 0xc0, 0x00, 0x00, 0x07, 0xc0, 0x00, - 0x1e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x00, 0x1f, 0x00, 0x18, 0x00, 0x00, - 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x03, - 0x80, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xe0, 0x03, - 0x00, 0x1f, 0x00, 0x18, 0x00, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3e, 0x00, 0x70, 0x01, 0xe0, 0x03, 0x00, 0x1e, 0x00, 0x10, 0x00, 0x00, - 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xc0, 0x03, - 0x00, 0x0e, 0x00, 0x10, 0x03, 0x80, 0x0c, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x30, 0x03, 0x80, - 0x0c, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x00, 0x00, 0x03, - 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0c, 0x00, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, - 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x70, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x00, 0x70, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, - 0x0c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0x1f, - 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x61, 0xff, 0xff, 0x0e, 0x00, 0x00, - 0xfe, 0x00, 0x70, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x01, 0xf0, 0x03, 0xff, - 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, - 0x7f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x70, 0x00, 0x00, 0xff, - 0x00, 0x00, 0x07, 0xf0, 0x01, 0xff, 0xfc, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, - 0x7e, 0x00, 0x70, 0x00, 0x1f, 0xff, 0x00, 0x00, 0xff, 0xf0, 0x00, 0x00, - 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x01, - 0xff, 0xf0, 0x0f, 0xff, 0x00, 0x00, 0x3e, 0x00, 0x70, 0x01, 0xff, 0xff, - 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf8, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x7f, 0xc0, 0x00, - 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, - 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x1f, - 0xe0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, - 0x00, 0x1f, 0xff, 0xf8, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x03, 0xfc, 0x00, - 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, 0x00, 0x1f, 0xff, 0xfc, 0x00, 0x00, - 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x00, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x1e, 0x00, 0x70, 0x01, 0xff, 0xff, - 0x80, 0x1f, 0xff, 0xfe, 0x00, 0x00, 0x1c, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xf0, 0x01, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x90, - 0x1f, 0x00, 0xf8, 0x03, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xff, 0x80, 0x00, - 0x7c, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x3f, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x1f, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfc, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x07, 0xfc, - 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, - 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, - 0x04, 0x07, 0xc0, 0x60, 0x00, 0xff, 0xc0, 0x01, 0x81, 0xe0, 0x7c, 0x00, - 0xf0, 0x00, 0x78, 0x00, 0x3c, 0x00, 0x0c, 0x00, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x07, 0xff, 0xff, 0xe0, 0x00, 0x7f, - 0x80, 0x01, 0x00, 0xe0, 0x7c, 0x00, 0xf0, 0x00, 0x38, 0x00, 0x1c, 0x00, - 0x0c, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, - 0x0f, 0xff, 0xff, 0xe0, 0x00, 0x3f, 0x80, 0x03, 0x00, 0xe0, 0x78, 0x00, - 0xf0, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00, 0x3f, - 0x00, 0x03, 0x00, 0x60, 0x78, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x0c, 0x00, - 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, - 0x3f, 0xf0, 0x1f, 0xf8, 0x00, 0x3f, 0x00, 0x03, 0x00, 0x60, 0x70, 0x00, - 0xf0, 0x00, 0x10, 0x00, 0x08, 0x00, 0x1c, 0x00, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x7f, 0x80, 0x01, 0xfe, 0x00, 0x3f, - 0x03, 0xfb, 0x00, 0x60, 0x70, 0x20, 0xe0, 0x30, 0x10, 0x18, 0x08, 0x0f, - 0xf8, 0x1c, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, - 0xfc, 0x00, 0x00, 0x7f, 0x00, 0x3e, 0x00, 0x7f, 0x00, 0x00, 0xe0, 0x60, - 0xe0, 0x38, 0x10, 0x18, 0x08, 0x00, 0x78, 0x1c, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xfc, 0x01, 0xf8, 0x00, 0x00, 0x3f, 0x80, 0x7e, - 0x00, 0x0f, 0x00, 0x00, 0xe0, 0x60, 0xe0, 0x30, 0x30, 0x18, 0x18, 0x00, - 0x78, 0x1c, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, - 0xe0, 0x00, 0x00, 0x0f, 0xf8, 0xfe, 0x00, 0x06, 0x00, 0x00, 0xe0, 0x60, - 0xe0, 0x60, 0x30, 0x30, 0x18, 0x00, 0x78, 0x00, 0x0f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, - 0x00, 0x06, 0x00, 0x00, 0xc0, 0xe0, 0xe0, 0x00, 0x30, 0x00, 0x18, 0x00, - 0xf8, 0x00, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x80, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x02, 0x00, 0x00, 0xc0, 0xe0, - 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0xf0, 0x00, 0x1f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, - 0xf0, 0x06, 0x04, 0x00, 0x80, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x70, 0x1f, - 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0xfc, 0x06, 0x04, 0x00, 0x80, 0x00, - 0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x1f, 0xf0, 0x00, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x30, 0x18, 0x00, 0x7f, 0xfc, - 0x00, 0x04, 0x0e, 0x00, 0x80, 0x00, 0xc0, 0x07, 0xe0, 0x03, 0xf0, 0x00, - 0x70, 0x20, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, 0x00, 0x04, 0x0e, 0x01, 0x00, 0x00, - 0xc0, 0xff, 0xe0, 0x7f, 0xf0, 0x00, 0x70, 0x30, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x3f, 0xf8, 0x00, 0x7f, 0xfc, - 0x00, 0x0c, 0x0e, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xc0, 0x7f, 0xe0, 0x00, - 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, - 0x00, 0x7f, 0xfc, 0x00, 0x7f, 0xfc, 0x00, 0x1c, 0x0f, 0x00, 0x03, 0xc0, - 0x80, 0xff, 0xc0, 0x7f, 0xe0, 0x00, 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0xfc, 0x7e, 0x00, 0x7f, 0xfc, - 0x00, 0x3c, 0x0f, 0x00, 0x07, 0xc0, 0x80, 0xff, 0xc0, 0x7f, 0xe0, 0x00, - 0x60, 0x30, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0x01, 0xf0, 0x0f, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x03, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xc0, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; +const unsigned char tft_bmp_logo_240135 [] PROGMEM = { + // 'adafruit_wippersnapper_logo, 240x135px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x7f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xff, 0x0e, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x76, 0x00, 0x00, 0xff, 0x0e, 0x00, 0x00, 0xed, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xff, 0x80, 0x00, 0xff, 0x0f, 0x00, 0x03, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x80, + 0x01, 0xff, 0x1f, 0x00, 0x03, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x01, 0xff, + 0x9f, 0x00, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x01, 0xff, 0x9f, 0x80, + 0x07, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x03, 0xcf, 0xbf, 0x80, 0x0f, 0xff, + 0xe0, 0xff, 0x07, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x03, 0x8f, 0xff, 0x80, 0x0f, 0xff, 0xf1, 0xff, + 0x8f, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x03, 0x3f, 0xff, 0xc0, 0x0f, 0xff, 0xf1, 0xff, 0x8f, 0xff, + 0xff, 0xc0, 0x7f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x1f, 0xff, 0xf0, 0x07, 0x7f, 0xff, 0xc0, 0x1f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf0, + 0x7f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, + 0xff, 0xf0, 0x07, 0x7f, 0xff, 0xc0, 0x1f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf0, 0x7f, 0xff, + 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, + 0x07, 0x3f, 0xff, 0xe0, 0x1f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0x80, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x0f, 0x9f, + 0xff, 0xe0, 0x1f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xe0, + 0x1f, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xc0, 0x07, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xf0, 0x1f, 0xff, + 0xf0, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xc0, 0x7f, 0xfe, 0x03, 0xfe, 0x38, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xe1, 0xff, + 0x8f, 0xfe, 0x3f, 0xfc, 0x7f, 0xe1, 0xff, 0xe0, 0xff, 0xff, 0x03, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, + 0x1f, 0xfc, 0x7f, 0xe0, 0xff, 0xe1, 0xff, 0xff, 0x83, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, + 0x7f, 0xe0, 0xff, 0xe3, 0xff, 0xff, 0xc3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, + 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, 0x7f, 0xe0, + 0xff, 0xe7, 0xff, 0xff, 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfc, + 0x7f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, 0x7f, 0xe0, 0xff, 0xe7, + 0xff, 0xff, 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, 0x7f, 0xe1, 0xff, 0xef, 0xfe, 0xff, + 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xc1, 0xff, 0x8f, 0xfe, 0x3f, 0xfc, 0x7f, 0xf1, 0xff, 0xcf, 0xfc, 0x7f, 0xf3, 0xff, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc1, 0xff, 0x8f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xcf, 0xfc, 0x7f, 0xf3, 0xff, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, + 0x8f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xf3, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0x8f, 0xff, + 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0x8f, 0xff, 0xff, 0xf8, + 0x7f, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0x8f, 0xff, 0xff, 0xf0, 0x7f, 0xff, + 0xff, 0x8f, 0xff, 0xff, 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x8f, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x9e, 0x00, + 0x00, 0xf1, 0xff, 0xff, 0x01, 0xff, 0x8f, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xfc, 0x0f, 0xfe, 0x00, + 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0x00, 0x00, 0x01, + 0xff, 0xff, 0x01, 0xff, 0x8f, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xf0, 0x0f, 0xfe, 0x00, 0x03, 0xff, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, + 0x81, 0xff, 0x8f, 0xff, 0xe0, 0x00, 0x7f, 0xfe, 0x00, 0x0f, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, 0x00, 0x1f, 0xf0, 0x00, 0xff, 0xff, 0xc1, 0xff, + 0x8f, 0xfe, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x07, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x03, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, + 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x07, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0f, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x00, 0x00, + 0x7f, 0xe0, 0x00, 0x07, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, + 0xff, 0xc0, 0x7f, 0xff, 0xff, 0xfc, 0x03, 0xff, 0xf1, 0xff, 0x8f, 0xfe, 0x00, 0x00, 0x7f, 0xe0, + 0x00, 0x03, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x01, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xf1, 0xff, 0x8f, 0xfe, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x01, + 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x07, 0xff, 0xff, + 0xff, 0xff, 0xc0, 0xff, 0xe1, 0xff, 0x07, 0xfc, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x7f, 0xff, + 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, + 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x03, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x07, 0xe0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0xff, 0xfb, 0xf8, 0x3f, 0x9f, 0xff, 0x00, 0x3f, 0xfe, 0x7e, 0x1f, 0xc3, 0xff, + 0x0f, 0xff, 0x87, 0xff, 0xc3, 0xff, 0xf3, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xff, 0xf0, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x7f, 0xfc, 0xff, 0x1f, 0x83, 0xff, 0x0f, 0xff, + 0xc7, 0xff, 0xe3, 0xff, 0xf3, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, + 0xf0, 0x00, 0x00, 0x1f, 0xff, 0xc0, 0xff, 0xfc, 0xff, 0x1f, 0x87, 0xff, 0x0f, 0xff, 0xc7, 0xff, + 0xe3, 0xff, 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, + 0x00, 0x0f, 0xff, 0xc0, 0xff, 0xfc, 0xff, 0x9f, 0x87, 0xff, 0x0f, 0xff, 0xe7, 0xff, 0xf3, 0xff, + 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x0f, 0xe0, 0x07, + 0xff, 0xc0, 0xff, 0xfc, 0xff, 0x9f, 0x8f, 0xff, 0x0f, 0xff, 0xef, 0xff, 0xf7, 0xff, 0xe7, 0xff, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x80, 0xff, 0xfe, 0x01, 0xff, 0xc1, + 0xfc, 0x04, 0xff, 0xbf, 0x8f, 0xdf, 0x1f, 0xcf, 0xef, 0xe7, 0xf7, 0xf0, 0x07, 0xe3, 0xf8, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x03, 0xff, 0xff, 0x80, 0xff, 0xc1, 0xff, 0x80, + 0xff, 0xff, 0x8f, 0x9f, 0x1f, 0xcf, 0xef, 0xe7, 0xf7, 0xff, 0x87, 0xe3, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x07, 0xff, 0xff, 0xe0, 0x7f, 0x81, 0xff, 0xf1, 0xff, 0xff, + 0x1f, 0x9f, 0x1f, 0x8f, 0xcf, 0xc7, 0xe7, 0xff, 0x87, 0xe3, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xc0, 0x1f, 0xff, 0xff, 0xf0, 0x02, 0x01, 0xff, 0xf9, 0xff, 0xff, 0x1f, 0x9f, + 0x1f, 0xdf, 0xcf, 0xcf, 0xe7, 0xff, 0x87, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xf9, 0xff, 0xff, 0x3f, 0x1f, 0x1f, 0xff, + 0xcf, 0xff, 0xe7, 0xff, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x7f, 0xf9, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0x9f, 0xff, + 0xcf, 0xff, 0x0f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xff, 0xfe, 0x00, 0x00, 0x0f, 0xf9, 0xfb, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x9f, 0xff, 0xcf, 0xe0, + 0x0f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x03, 0xf9, 0xfb, 0xff, 0x7f, 0xff, 0x3f, 0xff, 0x1f, 0xff, 0x0f, 0xe0, 0x0f, 0xff, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xcf, 0xe7, 0xff, 0x80, 0x03, + 0xff, 0xfb, 0xf9, 0xfe, 0x7f, 0xff, 0x3f, 0xf8, 0x1f, 0xfc, 0x0f, 0xff, 0x8f, 0xdf, 0xc0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xc0, 0x07, 0xff, 0x80, 0x03, 0xff, 0xfb, + 0xf1, 0xfe, 0xff, 0xff, 0xbf, 0x00, 0x1f, 0x80, 0x0f, 0xff, 0x8f, 0xcf, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xc0, 0x07, 0xff, 0x80, 0x03, 0xff, 0xf3, 0xf1, 0xfe, + 0xff, 0xff, 0xff, 0x00, 0x1f, 0x80, 0x1f, 0xff, 0x9f, 0xcf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xff, 0x80, 0x03, 0xff, 0x80, 0x03, 0xff, 0xe3, 0xf0, 0xff, 0xfc, 0x3f, + 0xff, 0x00, 0x3f, 0x80, 0x1f, 0xff, 0x9f, 0xcf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0xff, 0x03, 0x81, 0xff, 0x00, 0x03, 0xff, 0xc3, 0xf0, 0xff, 0xf8, 0x3f, 0xff, 0x00, + 0x3f, 0x80, 0x1f, 0xff, 0x9f, 0x8f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x0f, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, + 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, + 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 +}; // 'adafruit_wippersnapper_logo', 240x240px const unsigned char tft_bmp_logo_240240[] PROGMEM = { diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index b1f9479a1..b1d4766aa 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -155,13 +155,6 @@ void DisplayController::update(int32_t rssi, bool is_connected) { return; _last_bar_update = now; - // Early-out if nothing has changed - // and only consider WiFi changes +/-3dB - bool rssi_changed = abs(rssi - _statusbar_rssi) >= 3; - if (!rssi_changed && is_connected == _statusbar_mqtt_connected && 100 == _statusbar_bat) { - return; - } - // Get the driver instance for the display for (DisplayHardware *hw_instance : _hw_instances) { // Note: For now, battery is always 100% as we don't have a way to read it @@ -169,10 +162,6 @@ void DisplayController::update(int32_t rssi, bool is_connected) { hw_instance->updateStatusBar(rssi, 100, is_connected); } - // Update the cached status bar values - _statusbar_rssi = rssi; - _statusbar_mqtt_connected = is_connected; - _statusbar_bat = 100; // NOTE: Always 100%, for now WS.feedWDT(); WS.runNetFSM(); } \ No newline at end of file diff --git a/src/components/display/controller.h b/src/components/display/controller.h index eeffadfd8..cc519abe6 100644 --- a/src/components/display/controller.h +++ b/src/components/display/controller.h @@ -40,9 +40,6 @@ class DisplayController { private: std::vector _hw_instances; ///< Holds pointers to DisplayHardware instances - int8_t _statusbar_rssi; ///< RSSI value for status bar - uint8_t _statusbar_bat; ///< Battery level, as a percentage, for the status bar - bool _statusbar_mqtt_connected; ///< MQTT connection status for the status bar unsigned long _last_bar_update; ///< Timestamp of last status bar update }; extern Wippersnapper Ws; ///< Global WS instance diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index 8c71ed07b..242c2e50a 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -175,6 +175,14 @@ class dispDrvBase { int16_t _height; ///< Height of the display int16_t _width; ///< Width of the display uint8_t _rotation; ///< Rotation of the display + // statusbar properties + int _statusbar_icons_y; ///< Y position of status bar icons + int _statusbar_icon_battery_x; ///< X position of battery icon + int _statusbar_icon_wifi_x; ///< X position of WiFi icon + int _statusbar_icon_cloud_x; ///< X position of cloud icon + int8_t _statusbar_rssi; ///< RSSI value for status bar + uint8_t _statusbar_bat; ///< Battery level, as a percentage, for the status bar + bool _statusbar_mqtt_connected; ///< MQTT connection status for the status bar }; #endif // WS_DISP_DRV_BASE_H \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index 5d5eedd4c..f19af56ae 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -18,7 +18,13 @@ #include "dispDrvBase.h" #include -#define ST7789_TEXT_SZ_DEFAULT 2 ///< Default text size for ST7789 displays +#define ST7789_TEXT_SZ_DEFAULT 2 ///< Default text size for ST7789 displays +#define ST7789_STATUSBAR_HEIGHT 20 ///< Default status bar height +#define ST7789_STATUSBAR_ICON_SZ 16 ///< Default status bar icon size +#define ST7789_STATUSBAR_ICON_SPACING \ + 4 ///< Default spacing between status bar icons +#define ST7789_STATUSBAR_ICON_MARGIN \ + 5 ///< Default margin from edge of display to status bar icons /*! @brief Driver for ST7789-based TFT displays. @@ -52,8 +58,14 @@ class dispDrvSt7789 : public dispDrvBase { delete _display; _display = nullptr; } +// Turn off backlight #if defined(ARDUINO_FUNHOUSE_ESP32S2) digitalWrite(TFT_BACKLIGHT, LOW); +#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3_REVTFT) || \ + defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT) || \ + defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2_REVTFT) || \ + defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2_TFT) + digitalWrite(TFT_BACKLITE, LOW); #endif } @@ -73,10 +85,16 @@ class dispDrvSt7789 : public dispDrvBase { _display->fillScreen(ST77XX_BLACK); _display->setTextColor(ST77XX_WHITE); + // Turn on backlight #if defined(ARDUINO_FUNHOUSE_ESP32S2) - // Turn backlight on pinMode(TFT_BACKLIGHT, OUTPUT); digitalWrite(TFT_BACKLIGHT, HIGH); +#elif defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3_REVTFT) || \ + defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT) || \ + defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2_REVTFT) || \ + defined(ARDUINO_ADAFRUIT_FEATHER_ESP32S2_TFT) + pinMode(TFT_BACKLITE, OUTPUT); + digitalWrite(TFT_BACKLITE, HIGH); #endif return true; @@ -106,8 +124,8 @@ class dispDrvSt7789 : public dispDrvBase { // Display the appropriate splash screen based on resolution if (_width == 240 && _height == 240) { _display->drawBitmap(0, 0, tft_bmp_logo_240240, 240, 240, ST77XX_WHITE); - } else if (_width == 240 && _height == 135) { - _display->drawBitmap(0, 0, tft_bmp_logo_240135, 240, 135, ST77XX_BLACK); + } else if (_width == 135 && _height == 240) { + _display->drawBitmap(0, 0, tft_bmp_logo_240135, 240, 135, ST77XX_WHITE); } else { // Unsupported resolution return; @@ -123,28 +141,11 @@ class dispDrvSt7789 : public dispDrvBase { if (!_display) return; - // Configure status bar parameters based on resolution - if (_width == 240 && _height == 240) { - _status_bar_height = 20; - _status_bar_icon_sz = 16; - _status_bar_icon_spacing = 4; - _status_bar_icon_margin = 5; - } else if (_width == 240 && _height == 135) { - // TODO: The required icons are not added/implemented for 12px icons - _status_bar_height = 16; - _status_bar_icon_sz = 12; - _status_bar_icon_spacing = 3; - _status_bar_icon_margin = 4; - } else { - // Unsupported resolution - return; - } - // Clear the entire display buffer to remove splash screen _display->fillScreen(ST77XX_BLACK); // Draw status bar - _display->fillRect(0, 0, _display->width(), _status_bar_height, + _display->fillRect(0, 0, _display->width(), ST7789_STATUSBAR_HEIGHT, ST77XX_WHITE); // Draw username on left side of the status bar @@ -153,26 +154,23 @@ class dispDrvSt7789 : public dispDrvBase { _display->setCursor(5, 6); _display->print(io_username); - // Calculate icon positions and center vertically - int iconY = (_status_bar_height - _status_bar_icon_sz) / 2; - int batteryX = - _display->width() - _status_bar_icon_sz - _status_bar_icon_margin; - int wifiX = batteryX - _status_bar_icon_sz - _status_bar_icon_spacing; - int cloudX = wifiX - _status_bar_icon_sz - _status_bar_icon_spacing; - if (_height == 240) { - // Draw 16px icons on right side of the status bar - _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, - _status_bar_icon_sz, _status_bar_icon_sz, ST77XX_BLACK); - _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_full, _status_bar_icon_sz, - _status_bar_icon_sz, ST77XX_BLACK); - _display->drawBitmap(batteryX, iconY, epd_bmp_bat_full, - _status_bar_icon_sz, _status_bar_icon_sz, ST77XX_BLACK); - } else if (_height == 135) { - // TODO: Draw 12px icons on right side of the status bar - } else { - // Unsupported resolution - return; - } + // Calculate icon positions (rightmost side of status bar), center + // vertically + _statusbar_icons_y = (ST7789_STATUSBAR_HEIGHT - ST7789_STATUSBAR_ICON_SZ) / 2; + _statusbar_icon_battery_x = _display->width() - ST7789_STATUSBAR_ICON_SZ - + ST7789_STATUSBAR_ICON_MARGIN; + _statusbar_icon_wifi_x = _statusbar_icon_battery_x - ST7789_STATUSBAR_ICON_SZ - ST7789_STATUSBAR_ICON_SPACING; + _statusbar_icon_cloud_x = _statusbar_icon_wifi_x - ST7789_STATUSBAR_ICON_SZ - ST7789_STATUSBAR_ICON_SPACING; + // Draw icons + _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_online, + ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, + ST77XX_BLACK); + _display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, epd_bmp_wifi_full, + ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, + ST77XX_BLACK); + _display->drawBitmap(_statusbar_icon_battery_x, _statusbar_icons_y, epd_bmp_bat_full, + ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, + ST77XX_BLACK); } /*! @@ -189,41 +187,52 @@ class dispDrvSt7789 : public dispDrvBase { if (!_display) return; - WS_DEBUG_PRINTLN("Updating ST7789 status bar"); + // Only update wifi icon if the RSSI has changed significantly (+/-3dB) + bool update_rssi = abs(rssi - _statusbar_rssi) >= 3; + // Only update cloud icon if MQTT status has changed + bool update_mqtt = mqtt_status != _statusbar_mqtt_connected; - int iconY = (_status_bar_height - _status_bar_icon_sz) / 2; - int batteryX = _display->width() - _status_bar_icon_sz - _status_bar_icon_margin; - int wifiX = batteryX - _status_bar_icon_sz - _status_bar_icon_spacing; - int cloudX = wifiX - _status_bar_icon_sz - _status_bar_icon_spacing; + // No need to update if nothing has changed + if (!update_rssi && !update_mqtt) + return; + if (update_mqtt) { // Clear and draw the new cloud icon, based on MQTT connection status - _display->fillRect(cloudX, iconY, _status_bar_icon_sz, _status_bar_icon_sz, - ST77XX_WHITE); + _display->fillRect(_statusbar_icon_cloud_x, _statusbar_icons_y, ST7789_STATUSBAR_ICON_SZ, + ST7789_STATUSBAR_ICON_SZ, ST77XX_WHITE); if (mqtt_status) { - _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, - _status_bar_icon_sz, _status_bar_icon_sz, ST77XX_BLACK); + _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_online, + ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, + ST77XX_BLACK); } else { - _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_offline, - _status_bar_icon_sz, _status_bar_icon_sz, ST77XX_BLACK); + _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_offline, + ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, + ST77XX_BLACK); } + _statusbar_mqtt_connected = mqtt_status; + } - // Update WiFi icon only if RSSI has changed significantly (+/-3dB) - const unsigned char* wifi_icon = epd_bmp_wifi_no_signal; - if (rssi >= -50) { - wifi_icon = epd_bmp_wifi_full; - } else if (rssi < -50 && rssi >= -60) { - wifi_icon = epd_bmp_wifi_fair; - } else if (rssi < -60 && rssi >= -70) { - wifi_icon = epd_bmp_wifi_weak; - } else if (rssi < -70 && rssi >= -80) { - wifi_icon = epd_bmp_wifi_no_signal; - } else { - wifi_icon = epd_bmp_wifi_no_signal; - } - // Clear and draw the new WiFi icon, based on RSSI - _display->fillRect(wifiX, iconY, _status_bar_icon_sz, _status_bar_icon_sz, - ST77XX_WHITE); - _display->drawBitmap(wifiX, iconY, wifi_icon, _status_bar_icon_sz, _status_bar_icon_sz, ST77XX_BLACK); + // Update WiFi icon only if RSSI has changed significantly (+/-3dB) + if (update_rssi) { + const unsigned char *wifi_icon = epd_bmp_wifi_no_signal; + if (rssi >= -50) { + wifi_icon = epd_bmp_wifi_full; + } else if (rssi < -50 && rssi >= -60) { + wifi_icon = epd_bmp_wifi_fair; + } else if (rssi < -60 && rssi >= -70) { + wifi_icon = epd_bmp_wifi_weak; + } else if (rssi < -70 && rssi >= -80) { + wifi_icon = epd_bmp_wifi_no_signal; + } else { + wifi_icon = epd_bmp_wifi_no_signal; + } + // Clear and draw the new WiFi icon, based on RSSI + _display->fillRect(_statusbar_icon_wifi_x, _statusbar_icons_y, ST7789_STATUSBAR_ICON_SZ, + ST7789_STATUSBAR_ICON_SZ, ST77XX_WHITE); + _display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, wifi_icon, ST7789_STATUSBAR_ICON_SZ, + ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK); + _statusbar_rssi = rssi; + } } /*! @@ -240,9 +249,9 @@ class dispDrvSt7789 : public dispDrvBase { _display->setTextColor(ST77XX_WHITE); // Clear only the area below the status bar - _display->fillRect(0, _status_bar_height, _width, - _height - _status_bar_height, ST77XX_BLACK); - int16_t y_idx = _status_bar_height; + _display->fillRect(0, ST7789_STATUSBAR_HEIGHT, _width, + _height - ST7789_STATUSBAR_HEIGHT, ST77XX_BLACK); + int16_t y_idx = ST7789_STATUSBAR_HEIGHT; // Calculate the line height based on the text size (NOTE: base height is // 8px) @@ -285,12 +294,6 @@ class dispDrvSt7789 : public dispDrvBase { private: Adafruit_ST7789 *_display; - uint8_t _status_bar_height; ///< Height of the status bar, in pixels - uint8_t _status_bar_icon_sz; ///< Size of status bar icons, in pixels - uint8_t - _status_bar_icon_spacing; ///< Spacing between status bar icons, in pixels - uint8_t - _status_bar_icon_margin; ///< Right margin for status bar icons, in pixels }; #endif // WS_DISP_DRV_ST7789 \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index 8a8e96c1b..4b04d429a 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -22,6 +22,8 @@ 20 ///< Height of the status bar in pixels, assumes 16px icons #define STATUS_BAR_BORDER 1 ///< Border around the status bar in pixels #define STATUS_BAR_ICON_SZ 16 ///< Size of status bar icons in pixels +#define STATUS_BAR_ICON_SPACING 4 ///< Spacing between status bar icons in pixels +#define STATUS_BAR_ICON_MARGIN 5 ///< Margin from edge of display to status bar icons in pixels /*! @brief Driver for a ThinkInk 2.9" Grayscale 4-level EAAMFGN display. @@ -113,21 +115,17 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { _display->setCursor(5, 6); _display->print(io_username); - // Calculate icon positions and center vertically - int iconSpacing = 4; - int rightMargin = 5; - int iconY = - STATUS_BAR_BORDER + - ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2); - int batteryX = _display->width() - STATUS_BAR_ICON_SZ - rightMargin; - int wifiX = batteryX - STATUS_BAR_ICON_SZ - iconSpacing; - int cloudX = wifiX - STATUS_BAR_ICON_SZ - iconSpacing; + // Calculate status bar icon positions and center vertically + _statusbar_icons_y = STATUS_BAR_BORDER + ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2); + _statusbar_icon_battery_x = _display->width() - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_MARGIN; + _statusbar_icon_wifi_x = _statusbar_icon_battery_x - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_SPACING; + _statusbar_icon_cloud_x = _statusbar_icon_wifi_x - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_SPACING; // Draw icons on right side of the status bar - _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, + _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_online, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); - _display->drawBitmap(wifiX, iconY, epd_bmp_wifi_full, STATUS_BAR_ICON_SZ, + _display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, epd_bmp_wifi_full, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); - _display->drawBitmap(batteryX, iconY, epd_bmp_bat_full, STATUS_BAR_ICON_SZ, + _display->drawBitmap(_statusbar_icon_battery_x, _statusbar_icons_y, epd_bmp_bat_full, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); _display->display(); @@ -152,24 +150,14 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { // For EPD - redraws take 1-2 seconds, so only update the cloud state // Update cloud icon only if it changed state - int iconSpacing = 4; - int rightMargin = 5; - int iconY = - STATUS_BAR_BORDER + - ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / - 2); - int batteryX = _display->width() - STATUS_BAR_ICON_SZ - rightMargin; - int wifiX = batteryX - STATUS_BAR_ICON_SZ - iconSpacing; - int cloudX = wifiX - STATUS_BAR_ICON_SZ - iconSpacing; - // Clear and draw the new cloud icon, based on MQTT connection status - _display->fillRect(cloudX, iconY, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, + _display->fillRect(_statusbar_icon_cloud_x, _statusbar_icons_y, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_WHITE); if (mqtt_status == 21) { - _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_online, + _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_online, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); } else { - _display->drawBitmap(cloudX, iconY, epd_bmp_cloud_offline, + _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_offline, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); } diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 7dbb1a5b2..5432b15d6 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -49,7 +49,7 @@ static const std::map FactoryDrvDispTft = { int16_t miso) -> dispDrvBase * { return new dispDrvSt7789(cs, dc, mosi, sck, rst, miso); }}, - {"tft-154-wide-angle", + {"tft-114", [](int16_t cs, int16_t dc, int16_t mosi, int16_t sck, int16_t rst, int16_t miso) -> dispDrvBase * { return new dispDrvSt7789(cs, dc, mosi, sck, rst, miso); @@ -341,7 +341,13 @@ bool DisplayHardware::beginTft( _drvDisp->setWidth(config->width); _drvDisp->setHeight(config->height); + WS_DEBUG_PRINT("[display] TFT Resolution: "); + WS_DEBUG_PRINT(config->width); + WS_DEBUG_PRINT("x"); + WS_DEBUG_PRINTLN(config->height); _drvDisp->setRotation(config->rotation); + WS_DEBUG_PRINT("[display] TFT Rotation: "); + WS_DEBUG_PRINTLN(config->rotation); _drvDisp->begin(); return true; From 9fd844e81c3803aa0af7818a15b28e51c4e593ae Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 6 Oct 2025 10:59:05 -0400 Subject: [PATCH 63/76] Complete: EPD/MagTag implementation and test integration --- src/components/display/controller.cpp | 1 + .../display/drivers/dispDrvSt7789.h | 58 +++++++----- .../dispDrvThinkInkGrayscale4Eaamfgn.h | 93 ++++++++++++++----- src/components/display/hardware.cpp | 10 +- .../description/v1/description.pb.c | 2 +- .../description/v1/description.pb.h | 2 +- src/wippersnapper/display/v1/display.pb.c | 5 +- src/wippersnapper/display/v1/display.pb.h | 62 +++++-------- src/wippersnapper/ds18x20/v1/ds18x20.pb.c | 2 +- src/wippersnapper/ds18x20/v1/ds18x20.pb.h | 2 +- src/wippersnapper/i2c/v1/i2c.pb.c | 2 +- src/wippersnapper/i2c/v1/i2c.pb.h | 2 +- src/wippersnapper/pin/v1/pin.pb.c | 2 +- src/wippersnapper/pin/v1/pin.pb.h | 2 +- src/wippersnapper/pixels/v1/pixels.pb.c | 2 +- src/wippersnapper/pixels/v1/pixels.pb.h | 2 +- src/wippersnapper/pwm/v1/pwm.pb.c | 2 +- src/wippersnapper/pwm/v1/pwm.pb.h | 2 +- src/wippersnapper/servo/v1/servo.pb.c | 2 +- src/wippersnapper/servo/v1/servo.pb.h | 2 +- src/wippersnapper/signal/v1/signal.pb.c | 2 +- src/wippersnapper/signal/v1/signal.pb.h | 2 +- src/wippersnapper/uart/v1/uart.pb.c | 2 +- src/wippersnapper/uart/v1/uart.pb.h | 2 +- 24 files changed, 151 insertions(+), 114 deletions(-) diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index b1d4766aa..7a16cc9e6 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -159,6 +159,7 @@ void DisplayController::update(int32_t rssi, bool is_connected) { for (DisplayHardware *hw_instance : _hw_instances) { // Note: For now, battery is always 100% as we don't have a way to read it // yet. + WS_DEBUG_PRINTLN("[display] Updating status bar..."); hw_instance->updateStatusBar(rssi, 100, is_connected); } diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index f19af56ae..e10df2b66 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -127,7 +127,7 @@ class dispDrvSt7789 : public dispDrvBase { } else if (_width == 135 && _height == 240) { _display->drawBitmap(0, 0, tft_bmp_logo_240135, 240, 135, ST77XX_WHITE); } else { - // Unsupported resolution + // Unsupported resolution detected, skip splash screen return; } @@ -156,21 +156,26 @@ class dispDrvSt7789 : public dispDrvBase { // Calculate icon positions (rightmost side of status bar), center // vertically - _statusbar_icons_y = (ST7789_STATUSBAR_HEIGHT - ST7789_STATUSBAR_ICON_SZ) / 2; + _statusbar_icons_y = + (ST7789_STATUSBAR_HEIGHT - ST7789_STATUSBAR_ICON_SZ) / 2; _statusbar_icon_battery_x = _display->width() - ST7789_STATUSBAR_ICON_SZ - - ST7789_STATUSBAR_ICON_MARGIN; - _statusbar_icon_wifi_x = _statusbar_icon_battery_x - ST7789_STATUSBAR_ICON_SZ - ST7789_STATUSBAR_ICON_SPACING; - _statusbar_icon_cloud_x = _statusbar_icon_wifi_x - ST7789_STATUSBAR_ICON_SZ - ST7789_STATUSBAR_ICON_SPACING; + ST7789_STATUSBAR_ICON_MARGIN; + _statusbar_icon_wifi_x = _statusbar_icon_battery_x - + ST7789_STATUSBAR_ICON_SZ - + ST7789_STATUSBAR_ICON_SPACING; + _statusbar_icon_cloud_x = _statusbar_icon_wifi_x - + ST7789_STATUSBAR_ICON_SZ - + ST7789_STATUSBAR_ICON_SPACING; // Draw icons - _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_online, - ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, - ST77XX_BLACK); - _display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, epd_bmp_wifi_full, - ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, - ST77XX_BLACK); - _display->drawBitmap(_statusbar_icon_battery_x, _statusbar_icons_y, epd_bmp_bat_full, - ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, - ST77XX_BLACK); + _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, + epd_bmp_cloud_online, ST7789_STATUSBAR_ICON_SZ, + ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK); + _display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, + epd_bmp_wifi_full, ST7789_STATUSBAR_ICON_SZ, + ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK); + _display->drawBitmap(_statusbar_icon_battery_x, _statusbar_icons_y, + epd_bmp_bat_full, ST7789_STATUSBAR_ICON_SZ, + ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK); } /*! @@ -198,16 +203,17 @@ class dispDrvSt7789 : public dispDrvBase { if (update_mqtt) { // Clear and draw the new cloud icon, based on MQTT connection status - _display->fillRect(_statusbar_icon_cloud_x, _statusbar_icons_y, ST7789_STATUSBAR_ICON_SZ, - ST7789_STATUSBAR_ICON_SZ, ST77XX_WHITE); + _display->fillRect(_statusbar_icon_cloud_x, _statusbar_icons_y, + ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, + ST77XX_WHITE); if (mqtt_status) { - _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_online, - ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, - ST77XX_BLACK); + _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, + epd_bmp_cloud_online, ST7789_STATUSBAR_ICON_SZ, + ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK); } else { - _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_offline, - ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, - ST77XX_BLACK); + _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, + epd_bmp_cloud_offline, ST7789_STATUSBAR_ICON_SZ, + ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK); } _statusbar_mqtt_connected = mqtt_status; } @@ -227,9 +233,11 @@ class dispDrvSt7789 : public dispDrvBase { wifi_icon = epd_bmp_wifi_no_signal; } // Clear and draw the new WiFi icon, based on RSSI - _display->fillRect(_statusbar_icon_wifi_x, _statusbar_icons_y, ST7789_STATUSBAR_ICON_SZ, - ST7789_STATUSBAR_ICON_SZ, ST77XX_WHITE); - _display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, wifi_icon, ST7789_STATUSBAR_ICON_SZ, + _display->fillRect(_statusbar_icon_wifi_x, _statusbar_icons_y, + ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, + ST77XX_WHITE); + _display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, + wifi_icon, ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK); _statusbar_rssi = rssi; } diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index 4b04d429a..a06f5062f 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -22,8 +22,10 @@ 20 ///< Height of the status bar in pixels, assumes 16px icons #define STATUS_BAR_BORDER 1 ///< Border around the status bar in pixels #define STATUS_BAR_ICON_SZ 16 ///< Size of status bar icons in pixels -#define STATUS_BAR_ICON_SPACING 4 ///< Spacing between status bar icons in pixels -#define STATUS_BAR_ICON_MARGIN 5 ///< Margin from edge of display to status bar icons in pixels +#define STATUS_BAR_ICON_SPACING \ + 4 ///< Spacing between status bar icons in pixels +#define STATUS_BAR_ICON_MARGIN \ + 5 ///< Margin from edge of display to status bar icons in pixels /*! @brief Driver for a ThinkInk 2.9" Grayscale 4-level EAAMFGN display. @@ -73,7 +75,6 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { // Initialize the display _display->begin(mode); // Configure display settings - _text_sz = 3; _display->setTextSize(_text_sz); _display->setTextColor(EPD_BLACK); _display->setTextWrap(false); @@ -116,16 +117,24 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { _display->print(io_username); // Calculate status bar icon positions and center vertically - _statusbar_icons_y = STATUS_BAR_BORDER + ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2); - _statusbar_icon_battery_x = _display->width() - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_MARGIN; - _statusbar_icon_wifi_x = _statusbar_icon_battery_x - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_SPACING; - _statusbar_icon_cloud_x = _statusbar_icon_wifi_x - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_SPACING; + _statusbar_icons_y = + STATUS_BAR_BORDER + + ((STATUS_BAR_HEIGHT - 2 * STATUS_BAR_BORDER - STATUS_BAR_ICON_SZ) / 2); + _statusbar_icon_battery_x = + _display->width() - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_MARGIN; + _statusbar_icon_wifi_x = _statusbar_icon_battery_x - STATUS_BAR_ICON_SZ - + STATUS_BAR_ICON_SPACING; + _statusbar_icon_cloud_x = + _statusbar_icon_wifi_x - STATUS_BAR_ICON_SZ - STATUS_BAR_ICON_SPACING; // Draw icons on right side of the status bar - _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_online, - STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); - _display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, epd_bmp_wifi_full, STATUS_BAR_ICON_SZ, + _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, + epd_bmp_cloud_online, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); - _display->drawBitmap(_statusbar_icon_battery_x, _statusbar_icons_y, epd_bmp_bat_full, STATUS_BAR_ICON_SZ, + _display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, + epd_bmp_wifi_full, STATUS_BAR_ICON_SZ, + STATUS_BAR_ICON_SZ, EPD_BLACK); + _display->drawBitmap(_statusbar_icon_battery_x, _statusbar_icons_y, + epd_bmp_bat_full, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); _display->display(); @@ -145,21 +154,54 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { if (!_display) return; - bool do_update = false; + // Only update wifi icon if the RSSI has changed significantly (+/- 5dB) + bool update_rssi = abs(rssi - _statusbar_rssi) >= 5; + // Only update cloud icon if MQTT status has changed + bool update_mqtt = mqtt_status != _statusbar_mqtt_connected; - // For EPD - redraws take 1-2 seconds, so only update the cloud state + // No need to update if nothing has changed + if (!update_rssi && !update_mqtt) + return; - // Update cloud icon only if it changed state - // Clear and draw the new cloud icon, based on MQTT connection status - _display->fillRect(_statusbar_icon_cloud_x, _statusbar_icons_y, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, - EPD_WHITE); - if (mqtt_status == 21) { - _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_online, - STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + if (update_mqtt) { + // updating the RSSI occurs too frequently to be practical + _display->fillRect(_statusbar_icon_cloud_x, _statusbar_icons_y, + STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_WHITE); + if (mqtt_status) { + _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, + epd_bmp_cloud_online, STATUS_BAR_ICON_SZ, + STATUS_BAR_ICON_SZ, EPD_BLACK); + } else { + _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, + epd_bmp_cloud_offline, STATUS_BAR_ICON_SZ, + STATUS_BAR_ICON_SZ, EPD_BLACK); + } + _statusbar_mqtt_connected = mqtt_status; + } + + // Update WiFi icon only if RSSI has changed significantly (+/-3dB) + if (update_rssi) { + const unsigned char *wifi_icon = epd_bmp_wifi_no_signal; + if (rssi >= -50) { + wifi_icon = epd_bmp_wifi_full; + } else if (rssi < -50 && rssi >= -60) { + wifi_icon = epd_bmp_wifi_fair; + } else if (rssi < -60 && rssi >= -70) { + wifi_icon = epd_bmp_wifi_weak; + } else if (rssi < -70 && rssi >= -80) { + wifi_icon = epd_bmp_wifi_no_signal; } else { - _display->drawBitmap(_statusbar_icon_cloud_x, _statusbar_icons_y, epd_bmp_cloud_offline, - STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_BLACK); + wifi_icon = epd_bmp_wifi_no_signal; } + // Clear and draw the new WiFi icon, based on RSSI + _display->fillRect(_statusbar_icon_wifi_x, _statusbar_icons_y, + STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, + EPD_WHITE); + _display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, + wifi_icon, STATUS_BAR_ICON_SZ, + STATUS_BAR_ICON_SZ, EPD_BLACK); + _statusbar_rssi = rssi; + } _display->display(); } @@ -178,7 +220,8 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { // Clear only the area below the status bar _display->fillRect(0, STATUS_BAR_HEIGHT, _display->width(), _display->height() - STATUS_BAR_HEIGHT, EPD_WHITE); - int16_t y_idx = STATUS_BAR_HEIGHT; + // Add padding between status bar and text content + int16_t y_idx = STATUS_BAR_HEIGHT + 4; _display->setCursor(0, y_idx); // Calculate the line height based on the text size (NOTE: base height is @@ -186,6 +229,10 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { int16_t line_height = 8 * _text_sz; uint16_t c_idx = 0; size_t msg_size = strlen(message); + + // Reset the text size to the configured value before we write + _display->setTextSize(_text_sz); + for (size_t i = 0; i < msg_size && c_idx < msg_size; i++) { if (y_idx + line_height > _height) break; diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 5432b15d6..38f9148f0 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -248,6 +248,9 @@ bool DisplayHardware::beginEPD( _drvDisp = nullptr; return false; } + WS_DEBUG_PRINTLN("[display] Text Magnification: "); + WS_DEBUG_PRINTLN(config->text_size); + _drvDisp->setTextSize(config->text_size); if (!_drvDisp->begin(epd_mode)) { WS_DEBUG_PRINTLN("[display] Failed to begin display driver!"); @@ -341,13 +344,8 @@ bool DisplayHardware::beginTft( _drvDisp->setWidth(config->width); _drvDisp->setHeight(config->height); - WS_DEBUG_PRINT("[display] TFT Resolution: "); - WS_DEBUG_PRINT(config->width); - WS_DEBUG_PRINT("x"); - WS_DEBUG_PRINTLN(config->height); _drvDisp->setRotation(config->rotation); - WS_DEBUG_PRINT("[display] TFT Rotation: "); - WS_DEBUG_PRINTLN(config->rotation); + _drvDisp->setTextSize(config->text_size); _drvDisp->begin(); return true; diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index 2b54f9002..3a561a76e 100644 --- a/src/wippersnapper/description/v1/description.pb.c +++ b/src/wippersnapper/description/v1/description.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #include "wippersnapper/description/v1/description.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/description/v1/description.pb.h b/src/wippersnapper/description/v1/description.pb.h index 2373d1001..f276adbe7 100644 --- a/src/wippersnapper/description/v1/description.pb.h +++ b/src/wippersnapper/description/v1/description.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #ifndef PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DESCRIPTION_V1_WIPPERSNAPPER_DESCRIPTION_V1_DESCRIPTION_PB_H_INCLUDED diff --git a/src/wippersnapper/display/v1/display.pb.c b/src/wippersnapper/display/v1/display.pb.c index 87204989a..56076ede4 100644 --- a/src/wippersnapper/display/v1/display.pb.c +++ b/src/wippersnapper/display/v1/display.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #include "wippersnapper/display/v1/display.pb.h" #if PB_PROTO_HEADER_VERSION != 40 @@ -9,9 +9,6 @@ PB_BIND(wippersnapper_display_v1_EpdSpiConfig, wippersnapper_display_v1_EpdSpiConfig, AUTO) -PB_BIND(wippersnapper_display_v1_EPDWriteOptions, wippersnapper_display_v1_EPDWriteOptions, AUTO) - - PB_BIND(wippersnapper_display_v1_EPDConfig, wippersnapper_display_v1_EPDConfig, AUTO) diff --git a/src/wippersnapper/display/v1/display.pb.h b/src/wippersnapper/display/v1/display.pb.h index 3e49c4e1a..33b91cb7d 100644 --- a/src/wippersnapper/display/v1/display.pb.h +++ b/src/wippersnapper/display/v1/display.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #ifndef PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DISPLAY_V1_WIPPERSNAPPER_DISPLAY_V1_DISPLAY_PB_H_INCLUDED @@ -50,9 +50,12 @@ typedef struct _wippersnapper_display_v1_DisplayWrite { char message[1024]; } wippersnapper_display_v1_DisplayWrite; -typedef struct _wippersnapper_display_v1_EPDWriteOptions { +typedef struct _wippersnapper_display_v1_EPDConfig { + wippersnapper_display_v1_EPDMode mode; + int32_t width; + int32_t height; int32_t text_size; -} wippersnapper_display_v1_EPDWriteOptions; +} wippersnapper_display_v1_EPDConfig; typedef struct _wippersnapper_display_v1_EpdSpiConfig { int32_t bus; @@ -67,6 +70,7 @@ typedef struct _wippersnapper_display_v1_TftConfig { int32_t width; int32_t height; int32_t rotation; + int32_t text_size; } wippersnapper_display_v1_TftConfig; typedef struct _wippersnapper_display_v1_TftSpiConfig { @@ -79,14 +83,6 @@ typedef struct _wippersnapper_display_v1_TftSpiConfig { char pin_miso[6]; } wippersnapper_display_v1_TftSpiConfig; -typedef struct _wippersnapper_display_v1_EPDConfig { - wippersnapper_display_v1_EPDMode mode; - bool has_options; - wippersnapper_display_v1_EPDWriteOptions options; - int32_t width; - int32_t height; -} wippersnapper_display_v1_EPDConfig; - typedef struct _wippersnapper_display_v1_DisplayAddOrReplace { wippersnapper_display_v1_DisplayType type; wippersnapper_display_v1_DisplayDriver driver; @@ -124,20 +120,18 @@ extern "C" { /* Initializer values for message structs */ #define wippersnapper_display_v1_EpdSpiConfig_init_default {0, "", "", "", "", ""} -#define wippersnapper_display_v1_EPDWriteOptions_init_default {0} -#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN, false, wippersnapper_display_v1_EPDWriteOptions_init_default, 0, 0} +#define wippersnapper_display_v1_EPDConfig_init_default {_wippersnapper_display_v1_EPDMode_MIN, 0, 0, 0} #define wippersnapper_display_v1_TftSpiConfig_init_default {0, "", "", "", "", "", ""} -#define wippersnapper_display_v1_TftConfig_init_default {0, 0, 0} +#define wippersnapper_display_v1_TftConfig_init_default {0, 0, 0, 0} #define wippersnapper_display_v1_DisplayAddOrReplace_init_default {_wippersnapper_display_v1_DisplayType_MIN, _wippersnapper_display_v1_DisplayDriver_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_default}, 0, {wippersnapper_display_v1_EPDConfig_init_default}} #define wippersnapper_display_v1_DisplayRemove_init_default {""} #define wippersnapper_display_v1_DisplayWrite_init_default {"", ""} #define wippersnapper_display_v1_DisplayAddedOrReplaced_init_default {"", 0} #define wippersnapper_display_v1_DisplayRemoved_init_default {"", 0} #define wippersnapper_display_v1_EpdSpiConfig_init_zero {0, "", "", "", "", ""} -#define wippersnapper_display_v1_EPDWriteOptions_init_zero {0} -#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN, false, wippersnapper_display_v1_EPDWriteOptions_init_zero, 0, 0} +#define wippersnapper_display_v1_EPDConfig_init_zero {_wippersnapper_display_v1_EPDMode_MIN, 0, 0, 0} #define wippersnapper_display_v1_TftSpiConfig_init_zero {0, "", "", "", "", "", ""} -#define wippersnapper_display_v1_TftConfig_init_zero {0, 0, 0} +#define wippersnapper_display_v1_TftConfig_init_zero {0, 0, 0, 0} #define wippersnapper_display_v1_DisplayAddOrReplace_init_zero {_wippersnapper_display_v1_DisplayType_MIN, _wippersnapper_display_v1_DisplayDriver_MIN, "", 0, {wippersnapper_display_v1_EpdSpiConfig_init_zero}, 0, {wippersnapper_display_v1_EPDConfig_init_zero}} #define wippersnapper_display_v1_DisplayRemove_init_zero {""} #define wippersnapper_display_v1_DisplayWrite_init_zero {"", ""} @@ -152,7 +146,10 @@ extern "C" { #define wippersnapper_display_v1_DisplayRemoved_did_remove_tag 2 #define wippersnapper_display_v1_DisplayWrite_name_tag 1 #define wippersnapper_display_v1_DisplayWrite_message_tag 2 -#define wippersnapper_display_v1_EPDWriteOptions_text_size_tag 1 +#define wippersnapper_display_v1_EPDConfig_mode_tag 1 +#define wippersnapper_display_v1_EPDConfig_width_tag 2 +#define wippersnapper_display_v1_EPDConfig_height_tag 3 +#define wippersnapper_display_v1_EPDConfig_text_size_tag 4 #define wippersnapper_display_v1_EpdSpiConfig_bus_tag 1 #define wippersnapper_display_v1_EpdSpiConfig_pin_dc_tag 2 #define wippersnapper_display_v1_EpdSpiConfig_pin_rst_tag 3 @@ -162,6 +159,7 @@ extern "C" { #define wippersnapper_display_v1_TftConfig_width_tag 1 #define wippersnapper_display_v1_TftConfig_height_tag 2 #define wippersnapper_display_v1_TftConfig_rotation_tag 3 +#define wippersnapper_display_v1_TftConfig_text_size_tag 4 #define wippersnapper_display_v1_TftSpiConfig_bus_tag 1 #define wippersnapper_display_v1_TftSpiConfig_pin_cs_tag 2 #define wippersnapper_display_v1_TftSpiConfig_pin_dc_tag 3 @@ -169,10 +167,6 @@ extern "C" { #define wippersnapper_display_v1_TftSpiConfig_pin_sck_tag 5 #define wippersnapper_display_v1_TftSpiConfig_pin_rst_tag 6 #define wippersnapper_display_v1_TftSpiConfig_pin_miso_tag 7 -#define wippersnapper_display_v1_EPDConfig_mode_tag 1 -#define wippersnapper_display_v1_EPDConfig_options_tag 2 -#define wippersnapper_display_v1_EPDConfig_width_tag 3 -#define wippersnapper_display_v1_EPDConfig_height_tag 4 #define wippersnapper_display_v1_DisplayAddOrReplace_type_tag 1 #define wippersnapper_display_v1_DisplayAddOrReplace_driver_tag 2 #define wippersnapper_display_v1_DisplayAddOrReplace_name_tag 3 @@ -192,19 +186,13 @@ X(a, STATIC, SINGULAR, STRING, pin_busy, 6) #define wippersnapper_display_v1_EpdSpiConfig_CALLBACK NULL #define wippersnapper_display_v1_EpdSpiConfig_DEFAULT NULL -#define wippersnapper_display_v1_EPDWriteOptions_FIELDLIST(X, a) \ -X(a, STATIC, SINGULAR, INT32, text_size, 1) -#define wippersnapper_display_v1_EPDWriteOptions_CALLBACK NULL -#define wippersnapper_display_v1_EPDWriteOptions_DEFAULT NULL - #define wippersnapper_display_v1_EPDConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, UENUM, mode, 1) \ -X(a, STATIC, OPTIONAL, MESSAGE, options, 2) \ -X(a, STATIC, SINGULAR, INT32, width, 3) \ -X(a, STATIC, SINGULAR, INT32, height, 4) +X(a, STATIC, SINGULAR, INT32, width, 2) \ +X(a, STATIC, SINGULAR, INT32, height, 3) \ +X(a, STATIC, SINGULAR, INT32, text_size, 4) #define wippersnapper_display_v1_EPDConfig_CALLBACK NULL #define wippersnapper_display_v1_EPDConfig_DEFAULT NULL -#define wippersnapper_display_v1_EPDConfig_options_MSGTYPE wippersnapper_display_v1_EPDWriteOptions #define wippersnapper_display_v1_TftSpiConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, bus, 1) \ @@ -220,7 +208,8 @@ X(a, STATIC, SINGULAR, STRING, pin_miso, 7) #define wippersnapper_display_v1_TftConfig_FIELDLIST(X, a) \ X(a, STATIC, SINGULAR, INT32, width, 1) \ X(a, STATIC, SINGULAR, INT32, height, 2) \ -X(a, STATIC, SINGULAR, INT32, rotation, 3) +X(a, STATIC, SINGULAR, INT32, rotation, 3) \ +X(a, STATIC, SINGULAR, INT32, text_size, 4) #define wippersnapper_display_v1_TftConfig_CALLBACK NULL #define wippersnapper_display_v1_TftConfig_DEFAULT NULL @@ -263,7 +252,6 @@ X(a, STATIC, SINGULAR, BOOL, did_remove, 2) #define wippersnapper_display_v1_DisplayRemoved_DEFAULT NULL extern const pb_msgdesc_t wippersnapper_display_v1_EpdSpiConfig_msg; -extern const pb_msgdesc_t wippersnapper_display_v1_EPDWriteOptions_msg; extern const pb_msgdesc_t wippersnapper_display_v1_EPDConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_TftSpiConfig_msg; extern const pb_msgdesc_t wippersnapper_display_v1_TftConfig_msg; @@ -275,7 +263,6 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; /* Defines for backwards compatibility with code written before nanopb-0.4.0 */ #define wippersnapper_display_v1_EpdSpiConfig_fields &wippersnapper_display_v1_EpdSpiConfig_msg -#define wippersnapper_display_v1_EPDWriteOptions_fields &wippersnapper_display_v1_EPDWriteOptions_msg #define wippersnapper_display_v1_EPDConfig_fields &wippersnapper_display_v1_EPDConfig_msg #define wippersnapper_display_v1_TftSpiConfig_fields &wippersnapper_display_v1_TftSpiConfig_msg #define wippersnapper_display_v1_TftConfig_fields &wippersnapper_display_v1_TftConfig_msg @@ -287,11 +274,10 @@ extern const pb_msgdesc_t wippersnapper_display_v1_DisplayRemoved_msg; /* Maximum encoded size of messages (where known) */ #define wippersnapper_display_v1_EpdSpiConfig_size 46 -#define wippersnapper_display_v1_EPDWriteOptions_size 11 -#define wippersnapper_display_v1_EPDConfig_size 37 +#define wippersnapper_display_v1_EPDConfig_size 35 #define wippersnapper_display_v1_TftSpiConfig_size 53 -#define wippersnapper_display_v1_TftConfig_size 33 -#define wippersnapper_display_v1_DisplayAddOrReplace_size 163 +#define wippersnapper_display_v1_TftConfig_size 44 +#define wippersnapper_display_v1_DisplayAddOrReplace_size 170 #define wippersnapper_display_v1_DisplayRemove_size 65 #define wippersnapper_display_v1_DisplayWrite_size 1091 #define wippersnapper_display_v1_DisplayAddedOrReplaced_size 67 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c index 0f7d99046..4cd1b262f 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.c +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #include "wippersnapper/ds18x20/v1/ds18x20.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h index 74db2d97c..4f0e69289 100644 --- a/src/wippersnapper/ds18x20/v1/ds18x20.pb.h +++ b/src/wippersnapper/ds18x20/v1/ds18x20.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #ifndef PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED #define PB_WIPPERSNAPPER_DS18X20_V1_WIPPERSNAPPER_DS18X20_V1_DS18X20_PB_H_INCLUDED diff --git a/src/wippersnapper/i2c/v1/i2c.pb.c b/src/wippersnapper/i2c/v1/i2c.pb.c index 835db99c1..04efb79af 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.c +++ b/src/wippersnapper/i2c/v1/i2c.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #include "wippersnapper/i2c/v1/i2c.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/i2c/v1/i2c.pb.h b/src/wippersnapper/i2c/v1/i2c.pb.h index 887ac4877..4ea4be122 100644 --- a/src/wippersnapper/i2c/v1/i2c.pb.h +++ b/src/wippersnapper/i2c/v1/i2c.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #ifndef PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED #define PB_WIPPERSNAPPER_I2C_V1_WIPPERSNAPPER_I2C_V1_I2C_PB_H_INCLUDED diff --git a/src/wippersnapper/pin/v1/pin.pb.c b/src/wippersnapper/pin/v1/pin.pb.c index 06d9e03ba..765b7b7c8 100644 --- a/src/wippersnapper/pin/v1/pin.pb.c +++ b/src/wippersnapper/pin/v1/pin.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #include "wippersnapper/pin/v1/pin.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pin/v1/pin.pb.h b/src/wippersnapper/pin/v1/pin.pb.h index c9d1eaf1c..c766d2682 100644 --- a/src/wippersnapper/pin/v1/pin.pb.h +++ b/src/wippersnapper/pin/v1/pin.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #ifndef PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIN_V1_WIPPERSNAPPER_PIN_V1_PIN_PB_H_INCLUDED diff --git a/src/wippersnapper/pixels/v1/pixels.pb.c b/src/wippersnapper/pixels/v1/pixels.pb.c index b506de3f9..ff5d30e4c 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.c +++ b/src/wippersnapper/pixels/v1/pixels.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #include "wippersnapper/pixels/v1/pixels.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pixels/v1/pixels.pb.h b/src/wippersnapper/pixels/v1/pixels.pb.h index c580f0b39..2b4dc0a02 100644 --- a/src/wippersnapper/pixels/v1/pixels.pb.h +++ b/src/wippersnapper/pixels/v1/pixels.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #ifndef PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PIXELS_V1_WIPPERSNAPPER_PIXELS_V1_PIXELS_PB_H_INCLUDED diff --git a/src/wippersnapper/pwm/v1/pwm.pb.c b/src/wippersnapper/pwm/v1/pwm.pb.c index 0894fa333..9d2dd8738 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.c +++ b/src/wippersnapper/pwm/v1/pwm.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #include "wippersnapper/pwm/v1/pwm.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/pwm/v1/pwm.pb.h b/src/wippersnapper/pwm/v1/pwm.pb.h index d626095e6..f5b7d13c2 100644 --- a/src/wippersnapper/pwm/v1/pwm.pb.h +++ b/src/wippersnapper/pwm/v1/pwm.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #ifndef PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED #define PB_WIPPERSNAPPER_PWM_V1_WIPPERSNAPPER_PWM_V1_PWM_PB_H_INCLUDED diff --git a/src/wippersnapper/servo/v1/servo.pb.c b/src/wippersnapper/servo/v1/servo.pb.c index 65bc7d9a2..4da53fd19 100644 --- a/src/wippersnapper/servo/v1/servo.pb.c +++ b/src/wippersnapper/servo/v1/servo.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #include "wippersnapper/servo/v1/servo.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/servo/v1/servo.pb.h b/src/wippersnapper/servo/v1/servo.pb.h index 24adc6293..c1277c853 100644 --- a/src/wippersnapper/servo/v1/servo.pb.h +++ b/src/wippersnapper/servo/v1/servo.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #ifndef PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SERVO_V1_WIPPERSNAPPER_SERVO_V1_SERVO_PB_H_INCLUDED diff --git a/src/wippersnapper/signal/v1/signal.pb.c b/src/wippersnapper/signal/v1/signal.pb.c index 44017e6df..ae5fbfe39 100644 --- a/src/wippersnapper/signal/v1/signal.pb.c +++ b/src/wippersnapper/signal/v1/signal.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #include "wippersnapper/signal/v1/signal.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/signal/v1/signal.pb.h b/src/wippersnapper/signal/v1/signal.pb.h index 164d582ad..793f3196d 100644 --- a/src/wippersnapper/signal/v1/signal.pb.h +++ b/src/wippersnapper/signal/v1/signal.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #ifndef PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED #define PB_WIPPERSNAPPER_SIGNAL_V1_WIPPERSNAPPER_SIGNAL_V1_SIGNAL_PB_H_INCLUDED diff --git a/src/wippersnapper/uart/v1/uart.pb.c b/src/wippersnapper/uart/v1/uart.pb.c index f02a90b25..7cdc00a5d 100644 --- a/src/wippersnapper/uart/v1/uart.pb.c +++ b/src/wippersnapper/uart/v1/uart.pb.c @@ -1,5 +1,5 @@ /* Automatically generated nanopb constant definitions */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #include "wippersnapper/uart/v1/uart.pb.h" #if PB_PROTO_HEADER_VERSION != 40 diff --git a/src/wippersnapper/uart/v1/uart.pb.h b/src/wippersnapper/uart/v1/uart.pb.h index fb3d5dc34..844a0bc1d 100644 --- a/src/wippersnapper/uart/v1/uart.pb.h +++ b/src/wippersnapper/uart/v1/uart.pb.h @@ -1,5 +1,5 @@ /* Automatically generated nanopb header */ -/* Generated by nanopb-0.4.5-dev at Wed Sep 10 20:43:29 2025. */ +/* Generated by nanopb-0.4.5-dev at Tue Sep 30 14:06:15 2025. */ #ifndef PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED #define PB_WIPPERSNAPPER_UART_V1_WIPPERSNAPPER_UART_V1_UART_PB_H_INCLUDED From 707383978e097b7b52b1fd76b5d8dc367a69ec24 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 6 Oct 2025 11:56:25 -0400 Subject: [PATCH 64/76] Fix: Text resize on Tft, Bug: Text resize improperly due to no deinit --- src/Wippersnapper_demo.ino.cpp | 26 +++++++++++++++++++ src/components/display/controller.cpp | 10 +++++++ .../display/drivers/dispDrvSt7789.h | 24 +++++------------ src/components/display/hardware.cpp | 16 ------------ 4 files changed, 42 insertions(+), 34 deletions(-) create mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp new file mode 100644 index 000000000..99a7cb422 --- /dev/null +++ b/src/Wippersnapper_demo.ino.cpp @@ -0,0 +1,26 @@ +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmp4dvs_pq5" +#include +# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +#include "Wippersnapper_Networking.h" +Wippersnapper_WiFi wipper; + + +#define WS_DEBUG +void setup(); +void loop(); +#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" +void setup() { + + wipper.provision(); + + Serial.begin(115200); + + + wipper.connect(); + +} + +void loop() { + wipper.run(); +} \ No newline at end of file diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 7a16cc9e6..7b89b8349 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -45,6 +45,16 @@ bool DisplayController::Handle_Display_AddOrReplace( WS_DEBUG_PRINT("[display] Adding or replacing display: "); WS_DEBUG_PRINTLN(msgAdd->name); + // Does this display hw instance already exist? + for (auto it = _hw_instances.begin(); it != _hw_instances.end(); ++it) { + if (strcmp((*it)->getName(), msgAdd->name) == 0) { + WS_DEBUG_PRINTLN("[display] Display instance already exists, removing..."); + delete *it; + _hw_instances.erase(it); + break; + } + } + // Configure display type display->setType(msgAdd->type); diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index e10df2b66..336556342 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -18,7 +18,6 @@ #include "dispDrvBase.h" #include -#define ST7789_TEXT_SZ_DEFAULT 2 ///< Default text size for ST7789 displays #define ST7789_STATUSBAR_HEIGHT 20 ///< Default status bar height #define ST7789_STATUSBAR_ICON_SZ 16 ///< Default status bar icon size #define ST7789_STATUSBAR_ICON_SPACING \ @@ -81,7 +80,6 @@ class dispDrvSt7789 : public dispDrvBase { _display->init(_width, _height); _display->setRotation(_rotation); - setTextSize(ST7789_TEXT_SZ_DEFAULT); _display->fillScreen(ST77XX_BLACK); _display->setTextColor(ST77XX_WHITE); @@ -100,20 +98,6 @@ class dispDrvSt7789 : public dispDrvBase { return true; } - /*! - @brief Sets the text size for the display. - @param s - The text size to set. - @note This method overrides the base class method to provide specific - functionality for the ST7789 driver. - */ - void setTextSize(uint8_t s) override { - if (!_display) - return; - _text_sz = s; - _display->setTextSize(s); - } - /*! @brief Displays the splash screen on the display. */ @@ -176,6 +160,12 @@ class dispDrvSt7789 : public dispDrvBase { _display->drawBitmap(_statusbar_icon_battery_x, _statusbar_icons_y, epd_bmp_bat_full, ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK); + + // Reset text color and size for main text area + _display->setTextColor(ST77XX_WHITE); + WS_DEBUG_PRINTLN("SB Text Size:"); + WS_DEBUG_PRINTLN(_text_sz); + _display->setTextSize(_text_sz); } /*! @@ -254,8 +244,6 @@ class dispDrvSt7789 : public dispDrvBase { if (_display == nullptr) return; - _display->setTextColor(ST77XX_WHITE); - // Clear only the area below the status bar _display->fillRect(0, ST7789_STATUSBAR_HEIGHT, _width, _height - ST7789_STATUSBAR_HEIGHT, ST77XX_BLACK); diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 38f9148f0..7228fe36f 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -216,19 +216,6 @@ bool DisplayHardware::beginEPD( return false; } -/* // For "magtag" component name, attempt to autodetect the driver type - if (strncmp(_name, "eink-29-grayscale-ssd1680", 6) == 0) { - if (detect_ssd1680(cs, dc, rst)) { - // Detected SSD1680, use EAAMFGN driver - strncpy(_name, "thinkink-gs4-eaamfgn", sizeof(_name) - 1); - _name[sizeof(_name) - 1] = '\0'; - } else { - // Did not detect SSD1680, use IL0373 driver - strncpy(_name, "thinkink-gs4-t5", sizeof(_name) - 1); - _name[sizeof(_name) - 1] = '\0'; - } - } */ - // Create display driver object using the factory function _drvDisp = CreateDrvDispEpd(_name, dc, rst, cs, srcs, busy); if (!_drvDisp) { @@ -332,9 +319,6 @@ bool DisplayHardware::beginTft( miso = parsePin(spi_config->pin_miso); } - // TODO: Implement Text_size based on future Protobuf that includes it - uint8_t text_sz; // Default text size - // Create display driver object using the factory function _drvDisp = CreateDrvDispTft(_name, cs, dc, mosi, sck, rst, miso); if (!_drvDisp) { From bbf104d65999dd9f27a2fb3baea6608746ab9cd3 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 6 Oct 2025 13:06:31 -0400 Subject: [PATCH 65/76] Refactor - DisplayHardware iterator functions, remove auto use explicit types --- src/Wippersnapper_demo.ino.cpp | 2 +- src/components/display/controller.cpp | 59 +++++++++++++++++++-------- src/components/display/controller.h | 2 +- 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp index 99a7cb422..43e22c23b 100644 --- a/src/Wippersnapper_demo.ino.cpp +++ b/src/Wippersnapper_demo.ino.cpp @@ -1,4 +1,4 @@ -# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmp4dvs_pq5" +# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmp000bzb8y" #include # 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" # 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 7b89b8349..2d2d548f0 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -46,13 +46,17 @@ bool DisplayController::Handle_Display_AddOrReplace( WS_DEBUG_PRINTLN(msgAdd->name); // Does this display hw instance already exist? - for (auto it = _hw_instances.begin(); it != _hw_instances.end(); ++it) { - if (strcmp((*it)->getName(), msgAdd->name) == 0) { - WS_DEBUG_PRINTLN("[display] Display instance already exists, removing..."); - delete *it; - _hw_instances.erase(it); - break; + DisplayHardware *existingDisplay = findDisplay(msgAdd->name); + if (existingDisplay != nullptr) { + WS_DEBUG_PRINTLN("[display] Display exists, removing..."); + for (std::vector::iterator it = _hw_instances.begin(); + it != _hw_instances.end(); ++it) { + if (*it == existingDisplay) { + delete *it; + _hw_instances.erase(it); + break; } + } } // Configure display type @@ -102,16 +106,25 @@ bool DisplayController::Handle_Display_AddOrReplace( */ bool DisplayController::Handle_Display_Remove( wippersnapper_display_v1_DisplayRemove *msgRemove) { - // Find the display instance by name - for (auto it = _hw_instances.begin(); it != _hw_instances.end(); ++it) { - if (strcmp((*it)->getName(), msgRemove->name) == 0) { + if (!msgRemove || !msgRemove->name) + return false; + + DisplayHardware *display = findDisplay(msgRemove->name); + + if (display == nullptr) + return false; // Display not found + + // Remove from vector + for (std::vector::iterator it = _hw_instances.begin(); + it != _hw_instances.end(); ++it) { + if (*it == display) { delete *it; _hw_instances.erase(it); WS_DEBUG_PRINTLN("[display] Display removed successfully!"); return true; } } - WS_DEBUG_PRINTLN("[display] Could not remove display, not found!"); + return false; } @@ -124,13 +137,7 @@ bool DisplayController::Handle_Display_Remove( bool DisplayController::Handle_Display_Write( wippersnapper_display_v1_DisplayWrite *msgWrite) { // Get the driver instance for the display - DisplayHardware *display = nullptr; - for (auto &hw_instance : _hw_instances) { - if (strcmp(hw_instance->getName(), msgWrite->name) == 0) { - display = hw_instance; - break; - } - } + DisplayHardware *display = findDisplay(msgWrite->name); // Early-out if driver instance not found if (!display) { @@ -175,4 +182,22 @@ void DisplayController::update(int32_t rssi, bool is_connected) { WS.feedWDT(); WS.runNetFSM(); +} + +/*! + * @brief Finds a DisplayHardware instance by its name. + * @param name The name of the display to find. + * @return Pointer to the DisplayHardware instance if found, nullptr otherwise. + */ +DisplayHardware* DisplayController::findDisplay(const char* name) { + if (name == nullptr) + return nullptr; + + for (std::vector::iterator it = _hw_instances.begin(); it != _hw_instances.end(); ++it) { + if (*it != nullptr && strcmp((*it)->getName(), name) == 0) { + return *it; + } + } + + return nullptr; } \ No newline at end of file diff --git a/src/components/display/controller.h b/src/components/display/controller.h index cc519abe6..32d080af7 100644 --- a/src/components/display/controller.h +++ b/src/components/display/controller.h @@ -36,8 +36,8 @@ class DisplayController { bool Handle_Display_Remove(wippersnapper_display_v1_DisplayRemove *msgRemove); bool Handle_Display_Write(wippersnapper_display_v1_DisplayWrite *msgWrite); void update(int32_t rssi, bool is_connected); - private: + DisplayHardware* findDisplay(const char* name); std::vector _hw_instances; ///< Holds pointers to DisplayHardware instances unsigned long _last_bar_update; ///< Timestamp of last status bar update From b148f52b904a5ba97bc6af23e0ed2c1b8aec4d89 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 6 Oct 2025 13:50:35 -0400 Subject: [PATCH 66/76] Test - FeatherRevS3 --- src/Wippersnapper_demo.ino.cpp | 26 ------------------- .../display/drivers/dispDrvSt7789.h | 2 -- 2 files changed, 28 deletions(-) delete mode 100644 src/Wippersnapper_demo.ino.cpp diff --git a/src/Wippersnapper_demo.ino.cpp b/src/Wippersnapper_demo.ino.cpp deleted file mode 100644 index 43e22c23b..000000000 --- a/src/Wippersnapper_demo.ino.cpp +++ /dev/null @@ -1,26 +0,0 @@ -# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmp000bzb8y" -#include -# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -# 16 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -#include "Wippersnapper_Networking.h" -Wippersnapper_WiFi wipper; - - -#define WS_DEBUG -void setup(); -void loop(); -#line 22 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo.ino" -void setup() { - - wipper.provision(); - - Serial.begin(115200); - - - wipper.connect(); - -} - -void loop() { - wipper.run(); -} \ No newline at end of file diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index 336556342..17decf538 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -163,8 +163,6 @@ class dispDrvSt7789 : public dispDrvBase { // Reset text color and size for main text area _display->setTextColor(ST77XX_WHITE); - WS_DEBUG_PRINTLN("SB Text Size:"); - WS_DEBUG_PRINTLN(_text_sz); _display->setTextSize(_text_sz); } From 2f0455505f90387d1aab889772bdbb1f34d337f1 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 6 Oct 2025 15:07:30 -0400 Subject: [PATCH 67/76] Add ThinkInk Lib --- library.properties | 4 ++-- src/Wippersnapper.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/library.properties b/library.properties index 020d6d698..f268e7fe5 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Adafruit WipperSnapper -version=1.0.0-beta.117 +version=1.0.0-beta.118 author=Adafruit maintainer=Adafruit sentence=Arduino application for Adafruit.io WipperSnapper @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper category=Communication url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino architectures=* -depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPA06_003, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit MLX90632 Library, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit AS5600 Library, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit BMP5xx Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit QMC5883P Library, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306 +depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library, Adafruit AS5600 Library, Adafruit BMP5xx Library, Adafruit MLX90632 Library, Adafruit EPD diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 25927ef57..6395bcb98 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -139,7 +139,7 @@ #endif #define WS_VERSION \ - "1.0.0-beta.117" ///< WipperSnapper app. version (semver-formatted) + "1.0.0-beta.119" ///< WipperSnapper app. version (semver-formatted) // Reserved Adafruit IO MQTT topics #define TOPIC_IO_THROTTLE "/throttle" ///< Adafruit IO Throttle MQTT Topic From efafb41b1c17fec4030b9aac6eea1c0b0d78e5de Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 6 Oct 2025 16:12:57 -0400 Subject: [PATCH 68/76] Add Dep: Adafruit SPA06_003 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index f268e7fe5..65447c727 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper category=Communication url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino architectures=* -depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library, Adafruit AS5600 Library, Adafruit BMP5xx Library, Adafruit MLX90632 Library, Adafruit EPD +depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library, Adafruit AS5600 Library, Adafruit BMP5xx Library, Adafruit MLX90632 Library, Adafruit EPD, Adafruit SPA06_003 From 58f574025cfab96b6b2f05152d1b75906fac74e6 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 6 Oct 2025 16:23:36 -0400 Subject: [PATCH 69/76] Add dep: Adafruit QMC5883P Library --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 65447c727..905925a78 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper category=Communication url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino architectures=* -depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library, Adafruit AS5600 Library, Adafruit BMP5xx Library, Adafruit MLX90632 Library, Adafruit EPD, Adafruit SPA06_003 +depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library, Adafruit AS5600 Library, Adafruit BMP5xx Library, Adafruit MLX90632 Library, Adafruit EPD, Adafruit SPA06_003, Adafruit QMC5883P Library From f5bd52b756503b3f6fc01883e7ae7e775bbebfb5 Mon Sep 17 00:00:00 2001 From: brentru Date: Mon, 6 Oct 2025 16:45:49 -0400 Subject: [PATCH 70/76] Clang --- src/Wippersnapper.cpp | 2 +- src/components/display/assets/icons.h | 82 +-- src/components/display/assets/splash.h | 597 ++++++++++-------- src/components/display/controller.cpp | 23 +- .../display/drivers/dispDrvSt7789.h | 2 +- .../dispDrvThinkInkGrayscale4Eaamfgn.h | 7 +- 6 files changed, 397 insertions(+), 316 deletions(-) diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 2815f2ef4..44d6afb1e 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2873,7 +2873,7 @@ void Wippersnapper::publishPinConfigComplete() { // Publish message WS_DEBUG_PRINTLN("Publishing to pin config complete..."); if (!WS._mqtt->publish(WS._topic_device_pin_config_complete, _message_buffer, - _message_len, 0)) { + _message_len, 0)) { WS_DEBUG_PRINTLN("Failed to publish pin config complete message!"); } else { WS_DEBUG_PRINTLN("Published pin config complete message!"); diff --git a/src/components/display/assets/icons.h b/src/components/display/assets/icons.h index 656decbf1..13183ff02 100644 --- a/src/components/display/assets/icons.h +++ b/src/components/display/assets/icons.h @@ -2,46 +2,46 @@ #define _ICONS_H_ #include -const unsigned char epd_bmp_cloud_online [] PROGMEM = { - // 'cloud-thin-full, 16x16px - 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0d, 0xc0, 0x18, 0x78, 0x10, 0x0c, 0x30, 0x04, 0x70, 0x0c, - 0xc0, 0x06, 0xc0, 0x03, 0xc0, 0x03, 0x40, 0x03, 0x70, 0x06, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00 -}; - -const unsigned char epd_bmp_cloud_offline [] PROGMEM = { - // 'cloud-xmark-thin-full, 16x16px - 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0d, 0xc0, 0x18, 0x78, 0x10, 0x0c, 0x30, 0x04, 0x73, 0xcc, - 0xe3, 0x86, 0xc3, 0xc3, 0xc3, 0xc3, 0x40, 0x03, 0x70, 0x06, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00 -}; - -const unsigned char epd_bmp_wifi_full [] PROGMEM = { - // 'wifi-thin-full, 16x16px - 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x3c, 0x3c, 0x70, 0x0e, 0xc0, 0x03, 0x03, 0xc0, 0x0f, 0xf0, - 0x1c, 0x38, 0x18, 0x18, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00 -}; - -const unsigned char epd_bmp_wifi_fair [] PROGMEM = { - // 'wifi-fair-thin-full, 16x16px - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x0f, 0xf0, - 0x1c, 0x38, 0x18, 0x18, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00 -}; - -const unsigned char epd_bmp_wifi_weak [] PROGMEM = { - // 'wifi-weak-thin-full, 16x16px - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00 -}; - -const unsigned char epd_bmp_wifi_no_signal [] PROGMEM = { - // 'wifi-slash-thin-full, 16x16px - 0x00, 0x00, 0x40, 0x00, 0x27, 0xc0, 0x1e, 0x38, 0x68, 0x00, 0x44, 0x03, 0x03, 0x00, 0x01, 0xe0, - 0x08, 0x90, 0x00, 0x40, 0x00, 0x20, 0x01, 0x90, 0x03, 0x88, 0x01, 0x84, 0x00, 0x02, 0x00, 0x00 -}; - -const unsigned char epd_bmp_bat_full [] PROGMEM = { - // 'battery-full-thin-full, 16x16px - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0xc0, 0x06, 0xff, 0xfa, 0xf0, 0x0b, 0xf0, 0x0b, - 0xf0, 0x0b, 0xf0, 0x0b, 0xff, 0xfa, 0xc0, 0x06, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; +const unsigned char epd_bmp_cloud_online[] PROGMEM = { + // 'cloud-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0d, 0xc0, 0x18, 0x78, 0x10, + 0x0c, 0x30, 0x04, 0x70, 0x0c, 0xc0, 0x06, 0xc0, 0x03, 0xc0, 0x03, + 0x40, 0x03, 0x70, 0x06, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char epd_bmp_cloud_offline[] PROGMEM = { + // 'cloud-xmark-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0d, 0xc0, 0x18, 0x78, 0x10, + 0x0c, 0x30, 0x04, 0x73, 0xcc, 0xe3, 0x86, 0xc3, 0xc3, 0xc3, 0xc3, + 0x40, 0x03, 0x70, 0x06, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char epd_bmp_wifi_full[] PROGMEM = { + // 'wifi-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x3c, 0x3c, 0x70, 0x0e, 0xc0, + 0x03, 0x03, 0xc0, 0x0f, 0xf0, 0x1c, 0x38, 0x18, 0x18, 0x00, 0x00, + 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char epd_bmp_wifi_fair[] PROGMEM = { + // 'wifi-fair-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0xc0, 0x0f, 0xf0, 0x1c, 0x38, 0x18, 0x18, 0x00, 0x00, + 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char epd_bmp_wifi_weak[] PROGMEM = { + // 'wifi-weak-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00}; + +const unsigned char epd_bmp_wifi_no_signal[] PROGMEM = { + // 'wifi-slash-thin-full, 16x16px + 0x00, 0x00, 0x40, 0x00, 0x27, 0xc0, 0x1e, 0x38, 0x68, 0x00, 0x44, + 0x03, 0x03, 0x00, 0x01, 0xe0, 0x08, 0x90, 0x00, 0x40, 0x00, 0x20, + 0x01, 0x90, 0x03, 0x88, 0x01, 0x84, 0x00, 0x02, 0x00, 0x00}; + +const unsigned char epd_bmp_bat_full[] PROGMEM = { + // 'battery-full-thin-full, 16x16px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0xc0, 0x06, 0xff, + 0xfa, 0xf0, 0x0b, 0xf0, 0x0b, 0xf0, 0x0b, 0xf0, 0x0b, 0xff, 0xfa, + 0xc0, 0x06, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #endif // _ICONS_H_ \ No newline at end of file diff --git a/src/components/display/assets/splash.h b/src/components/display/assets/splash.h index 57c5edb39..254a60b65 100644 --- a/src/components/display/assets/splash.h +++ b/src/components/display/assets/splash.h @@ -2,263 +2,346 @@ #define _SPLASH_H_ #include -const unsigned char tft_bmp_logo_240135 [] PROGMEM = { - // 'adafruit_wippersnapper_logo, 240x135px - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x08, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x7f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xff, 0x0e, 0x00, 0x00, 0x4c, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0x76, 0x00, 0x00, 0xff, 0x0e, 0x00, 0x00, 0xed, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, - 0xff, 0x80, 0x00, 0xff, 0x0f, 0x00, 0x03, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x80, - 0x01, 0xff, 0x1f, 0x00, 0x03, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x01, 0xff, - 0x9f, 0x00, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x01, 0xff, 0x9f, 0x80, - 0x07, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x03, 0xcf, 0xbf, 0x80, 0x0f, 0xff, - 0xe0, 0xff, 0x07, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x03, 0x8f, 0xff, 0x80, 0x0f, 0xff, 0xf1, 0xff, - 0x8f, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x03, 0x3f, 0xff, 0xc0, 0x0f, 0xff, 0xf1, 0xff, 0x8f, 0xff, - 0xff, 0xc0, 0x7f, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x1f, 0xff, 0xf0, 0x07, 0x7f, 0xff, 0xc0, 0x1f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf0, - 0x7f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, - 0xff, 0xf0, 0x07, 0x7f, 0xff, 0xc0, 0x1f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf0, 0x7f, 0xff, - 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, - 0x07, 0x3f, 0xff, 0xe0, 0x1f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0x80, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x0f, 0x9f, - 0xff, 0xe0, 0x1f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xe0, - 0x1f, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xc0, 0x07, 0xe0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xf0, 0x1f, 0xff, - 0xf0, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xc0, 0x7f, 0xfe, 0x03, 0xfe, 0x38, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xe1, 0xff, - 0x8f, 0xfe, 0x3f, 0xfc, 0x7f, 0xe1, 0xff, 0xe0, 0xff, 0xff, 0x03, 0xff, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf0, 0x3f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, - 0x1f, 0xfc, 0x7f, 0xe0, 0xff, 0xe1, 0xff, 0xff, 0x83, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0f, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, - 0x7f, 0xe0, 0xff, 0xe3, 0xff, 0xff, 0xc3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, - 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, 0x7f, 0xe0, - 0xff, 0xe7, 0xff, 0xff, 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfc, - 0x7f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, 0x7f, 0xe0, 0xff, 0xe7, - 0xff, 0xff, 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, 0x7f, 0xe1, 0xff, 0xef, 0xfe, 0xff, - 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xc1, 0xff, 0x8f, 0xfe, 0x3f, 0xfc, 0x7f, 0xf1, 0xff, 0xcf, 0xfc, 0x7f, 0xf3, 0xff, - 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xc1, 0xff, 0x8f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xcf, 0xfc, 0x7f, 0xf3, 0xff, 0xf0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, - 0x8f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xf3, 0xff, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0x8f, 0xff, - 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0x8f, 0xff, 0xff, 0xf8, - 0x7f, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0x8f, 0xff, 0xff, 0xf0, 0x7f, 0xff, - 0xff, 0x8f, 0xff, 0xff, 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x8f, 0xff, 0xff, 0xe0, 0x7f, 0xff, 0xff, 0x0f, - 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x9e, 0x00, - 0x00, 0xf1, 0xff, 0xff, 0x01, 0xff, 0x8f, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xfc, 0x0f, 0xfe, 0x00, - 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0x00, 0x00, 0x01, - 0xff, 0xff, 0x01, 0xff, 0x8f, 0xff, 0xff, 0x00, 0x7f, 0xff, 0xf0, 0x0f, 0xfe, 0x00, 0x03, 0xff, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, - 0x81, 0xff, 0x8f, 0xff, 0xe0, 0x00, 0x7f, 0xfe, 0x00, 0x0f, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, 0x00, 0x1f, 0xf0, 0x00, 0xff, 0xff, 0xc1, 0xff, - 0x8f, 0xfe, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x07, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x03, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, - 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x07, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x0f, 0xff, 0xe0, 0x1f, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x00, 0x00, - 0x7f, 0xe0, 0x00, 0x07, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, - 0xff, 0xc0, 0x7f, 0xff, 0xff, 0xfc, 0x03, 0xff, 0xf1, 0xff, 0x8f, 0xfe, 0x00, 0x00, 0x7f, 0xe0, - 0x00, 0x03, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x01, - 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xf1, 0xff, 0x8f, 0xfe, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x01, - 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x07, 0xff, 0xff, - 0xff, 0xff, 0xc0, 0xff, 0xe1, 0xff, 0x07, 0xfc, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x7f, 0xff, - 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x0f, 0xff, 0xff, 0xff, 0xff, - 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x03, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x07, 0xe0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0xff, 0xfb, 0xf8, 0x3f, 0x9f, 0xff, 0x00, 0x3f, 0xfe, 0x7e, 0x1f, 0xc3, 0xff, - 0x0f, 0xff, 0x87, 0xff, 0xc3, 0xff, 0xf3, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x03, 0xff, 0xf0, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x7f, 0xfc, 0xff, 0x1f, 0x83, 0xff, 0x0f, 0xff, - 0xc7, 0xff, 0xe3, 0xff, 0xf3, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, - 0xf0, 0x00, 0x00, 0x1f, 0xff, 0xc0, 0xff, 0xfc, 0xff, 0x1f, 0x87, 0xff, 0x0f, 0xff, 0xc7, 0xff, - 0xe3, 0xff, 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, - 0x00, 0x0f, 0xff, 0xc0, 0xff, 0xfc, 0xff, 0x9f, 0x87, 0xff, 0x0f, 0xff, 0xe7, 0xff, 0xf3, 0xff, - 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x0f, 0xe0, 0x07, - 0xff, 0xc0, 0xff, 0xfc, 0xff, 0x9f, 0x8f, 0xff, 0x0f, 0xff, 0xef, 0xff, 0xf7, 0xff, 0xe7, 0xff, - 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x80, 0xff, 0xfe, 0x01, 0xff, 0xc1, - 0xfc, 0x04, 0xff, 0xbf, 0x8f, 0xdf, 0x1f, 0xcf, 0xef, 0xe7, 0xf7, 0xf0, 0x07, 0xe3, 0xf8, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x03, 0xff, 0xff, 0x80, 0xff, 0xc1, 0xff, 0x80, - 0xff, 0xff, 0x8f, 0x9f, 0x1f, 0xcf, 0xef, 0xe7, 0xf7, 0xff, 0x87, 0xe3, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x07, 0xff, 0xff, 0xe0, 0x7f, 0x81, 0xff, 0xf1, 0xff, 0xff, - 0x1f, 0x9f, 0x1f, 0x8f, 0xcf, 0xc7, 0xe7, 0xff, 0x87, 0xe3, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xc0, 0x1f, 0xff, 0xff, 0xf0, 0x02, 0x01, 0xff, 0xf9, 0xff, 0xff, 0x1f, 0x9f, - 0x1f, 0xdf, 0xcf, 0xcf, 0xe7, 0xff, 0x87, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x00, 0xff, 0xf9, 0xff, 0xff, 0x3f, 0x1f, 0x1f, 0xff, - 0xcf, 0xff, 0xe7, 0xff, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x7f, 0xf9, 0xff, 0xff, 0x3f, 0x3f, 0x3f, 0xff, 0x9f, 0xff, - 0xcf, 0xff, 0x0f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, - 0xff, 0xfe, 0x00, 0x00, 0x0f, 0xf9, 0xfb, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x9f, 0xff, 0xcf, 0xe0, - 0x0f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x03, 0xf9, 0xfb, 0xff, 0x7f, 0xff, 0x3f, 0xff, 0x1f, 0xff, 0x0f, 0xe0, 0x0f, 0xff, - 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xcf, 0xe7, 0xff, 0x80, 0x03, - 0xff, 0xfb, 0xf9, 0xfe, 0x7f, 0xff, 0x3f, 0xf8, 0x1f, 0xfc, 0x0f, 0xff, 0x8f, 0xdf, 0xc0, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xc0, 0x07, 0xff, 0x80, 0x03, 0xff, 0xfb, - 0xf1, 0xfe, 0xff, 0xff, 0xbf, 0x00, 0x1f, 0x80, 0x0f, 0xff, 0x8f, 0xcf, 0xc0, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xc0, 0x07, 0xff, 0x80, 0x03, 0xff, 0xf3, 0xf1, 0xfe, - 0xff, 0xff, 0xff, 0x00, 0x1f, 0x80, 0x1f, 0xff, 0x9f, 0xcf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x03, 0xff, 0x80, 0x03, 0xff, 0x80, 0x03, 0xff, 0xe3, 0xf0, 0xff, 0xfc, 0x3f, - 0xff, 0x00, 0x3f, 0x80, 0x1f, 0xff, 0x9f, 0xcf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0xff, 0x03, 0x81, 0xff, 0x00, 0x03, 0xff, 0xc3, 0xf0, 0xff, 0xf8, 0x3f, 0xff, 0x00, - 0x3f, 0x80, 0x1f, 0xff, 0x9f, 0x8f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xfe, 0x0f, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, - 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, - 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00 -}; +const unsigned char tft_bmp_logo_240135[] PROGMEM = { + // 'adafruit_wippersnapper_logo, 240x135px + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, + 0x00, 0x7f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0xff, 0x0e, 0x00, 0x00, 0x4c, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x76, 0x00, + 0x00, 0xff, 0x0e, 0x00, 0x00, 0xed, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xff, 0x80, 0x00, 0xff, 0x0f, 0x00, 0x03, 0xff, + 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x80, + 0x01, 0xff, 0x1f, 0x00, 0x03, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x01, 0xff, 0x9f, 0x00, 0x07, 0xff, + 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, + 0x01, 0xff, 0x9f, 0x80, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, 0x03, 0xcf, 0xbf, 0x80, 0x0f, 0xff, + 0xe0, 0xff, 0x07, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0x80, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, + 0x03, 0x8f, 0xff, 0x80, 0x0f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0x80, + 0x7f, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x03, 0x3f, 0xff, 0xc0, 0x0f, 0xff, + 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, + 0x07, 0x7f, 0xff, 0xc0, 0x1f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf0, + 0x7f, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x07, 0x7f, 0xff, 0xc0, 0x1f, 0xff, + 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, + 0x07, 0x3f, 0xff, 0xe0, 0x1f, 0xff, 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf8, + 0x7f, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, 0x0f, 0x9f, 0xff, 0xe0, 0x1f, 0xff, + 0xf1, 0xff, 0x8f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xc0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0xf0, + 0x0f, 0xff, 0xff, 0xe0, 0x1f, 0xff, 0xf0, 0x00, 0x0f, 0xff, 0xff, 0xfc, + 0x7f, 0xff, 0xff, 0xc0, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0, 0x0f, 0xff, 0xff, 0xf0, 0x1f, 0xff, + 0xf0, 0x00, 0x0f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xc0, 0x7f, 0xfe, + 0x03, 0xfe, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, + 0x1f, 0xff, 0xff, 0xf0, 0x1f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x3f, 0xfc, + 0x7f, 0xe1, 0xff, 0xe0, 0xff, 0xff, 0x03, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xf0, 0x3f, 0xff, + 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, 0x7f, 0xe0, 0xff, 0xe1, 0xff, 0xff, + 0x83, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, + 0x1f, 0xff, 0xff, 0xf8, 0x3f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, + 0x7f, 0xe0, 0xff, 0xe3, 0xff, 0xff, 0xc3, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x3f, 0xff, 0xff, 0xf8, 0x3f, 0xff, + 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, 0x7f, 0xe0, 0xff, 0xe7, 0xff, 0xff, + 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfc, + 0x7f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, + 0x7f, 0xe0, 0xff, 0xe7, 0xff, 0xff, 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc1, 0xff, 0x8f, 0xfe, 0x1f, 0xfc, 0x7f, 0xe1, 0xff, 0xef, 0xfe, 0xff, + 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0x8f, 0xfe, 0x3f, 0xfc, + 0x7f, 0xf1, 0xff, 0xcf, 0xfc, 0x7f, 0xf3, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xc1, 0xff, 0x8f, 0xff, 0xff, 0xfc, 0x7f, 0xff, 0xff, 0xcf, 0xfc, 0x7f, + 0xf3, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc1, 0xff, 0x8f, 0xff, 0xff, 0xfc, + 0x7f, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xf3, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x81, 0xff, 0x8f, 0xff, 0xff, 0xf8, 0x7f, 0xff, 0xff, 0xcf, 0xff, 0xff, + 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0x8f, 0xff, 0xff, 0xf8, + 0x7f, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x81, 0xff, 0x8f, 0xff, 0xff, 0xf0, 0x7f, 0xff, 0xff, 0x8f, 0xff, 0xff, + 0xf3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0x8f, 0xff, 0xff, 0xe0, + 0x7f, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x9e, 0x00, 0x00, 0xf1, 0xff, 0xff, + 0x01, 0xff, 0x8f, 0xff, 0xff, 0xc0, 0x7f, 0xff, 0xfc, 0x0f, 0xfe, 0x00, + 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, + 0x80, 0x00, 0x00, 0x01, 0xff, 0xff, 0x01, 0xff, 0x8f, 0xff, 0xff, 0x00, + 0x7f, 0xff, 0xf0, 0x0f, 0xfe, 0x00, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, + 0x81, 0xff, 0x8f, 0xff, 0xe0, 0x00, 0x7f, 0xfe, 0x00, 0x0f, 0xff, 0xff, + 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xfe, + 0x00, 0x1f, 0xf0, 0x00, 0xff, 0xff, 0xc1, 0xff, 0x8f, 0xfe, 0x00, 0x00, + 0x7f, 0xe0, 0x00, 0x07, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf8, 0x03, 0xff, 0xff, 0x80, 0x3f, 0xff, + 0xe1, 0xff, 0x8f, 0xfe, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x07, 0xff, 0xff, + 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xe0, + 0x1f, 0xff, 0xff, 0xf0, 0x0f, 0xff, 0xe1, 0xff, 0x8f, 0xfe, 0x00, 0x00, + 0x7f, 0xe0, 0x00, 0x07, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xff, 0xc0, 0x7f, 0xff, 0xff, 0xfc, 0x03, 0xff, + 0xf1, 0xff, 0x8f, 0xfe, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x03, 0xff, 0xff, + 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xff, 0x01, + 0xff, 0xff, 0xff, 0xff, 0x01, 0xff, 0xf1, 0xff, 0x8f, 0xfe, 0x00, 0x00, + 0x7f, 0xe0, 0x00, 0x01, 0xff, 0xff, 0xe3, 0xff, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x0f, 0xfe, 0x07, 0xff, 0xff, 0xff, 0xff, 0xc0, 0xff, + 0xe1, 0xff, 0x07, 0xfc, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00, 0x7f, 0xff, + 0xc3, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0x0f, + 0xff, 0xff, 0xff, 0xff, 0xe0, 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x03, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x03, + 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, + 0xff, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x00, + 0x07, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, + 0xfb, 0xf8, 0x3f, 0x9f, 0xff, 0x00, 0x3f, 0xfe, 0x7e, 0x1f, 0xc3, 0xff, + 0x0f, 0xff, 0x87, 0xff, 0xc3, 0xff, 0xf3, 0xff, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf0, 0x00, 0x00, 0x1f, 0xff, 0x80, + 0x7f, 0xfc, 0xff, 0x1f, 0x83, 0xff, 0x0f, 0xff, 0xc7, 0xff, 0xe3, 0xff, + 0xf3, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, + 0xf0, 0x00, 0x00, 0x1f, 0xff, 0xc0, 0xff, 0xfc, 0xff, 0x1f, 0x87, 0xff, + 0x0f, 0xff, 0xc7, 0xff, 0xe3, 0xff, 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0xf0, 0x00, 0x00, 0x0f, 0xff, 0xc0, + 0xff, 0xfc, 0xff, 0x9f, 0x87, 0xff, 0x0f, 0xff, 0xe7, 0xff, 0xf3, 0xff, + 0xe3, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, + 0xc0, 0x0f, 0xe0, 0x07, 0xff, 0xc0, 0xff, 0xfc, 0xff, 0x9f, 0x8f, 0xff, + 0x0f, 0xff, 0xef, 0xff, 0xf7, 0xff, 0xe7, 0xff, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, 0x80, 0xff, 0xfe, 0x01, 0xff, 0xc1, + 0xfc, 0x04, 0xff, 0xbf, 0x8f, 0xdf, 0x1f, 0xcf, 0xef, 0xe7, 0xf7, 0xf0, + 0x07, 0xe3, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xff, + 0x03, 0xff, 0xff, 0x80, 0xff, 0xc1, 0xff, 0x80, 0xff, 0xff, 0x8f, 0x9f, + 0x1f, 0xcf, 0xef, 0xe7, 0xf7, 0xff, 0x87, 0xe3, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0xfc, 0x07, 0xff, 0xff, 0xe0, 0x7f, 0x81, + 0xff, 0xf1, 0xff, 0xff, 0x1f, 0x9f, 0x1f, 0x8f, 0xcf, 0xc7, 0xe7, 0xff, + 0x87, 0xe3, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, + 0x1f, 0xff, 0xff, 0xf0, 0x02, 0x01, 0xff, 0xf9, 0xff, 0xff, 0x1f, 0x9f, + 0x1f, 0xdf, 0xcf, 0xcf, 0xe7, 0xff, 0x87, 0xff, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x00, + 0xff, 0xf9, 0xff, 0xff, 0x3f, 0x1f, 0x1f, 0xff, 0xcf, 0xff, 0xe7, 0xff, + 0x07, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7f, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x7f, 0xf9, 0xff, 0xff, 0x3f, 0x3f, + 0x3f, 0xff, 0x9f, 0xff, 0xcf, 0xff, 0x0f, 0xff, 0xe0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, + 0x0f, 0xf9, 0xfb, 0xff, 0x3f, 0xff, 0x3f, 0xff, 0x9f, 0xff, 0xcf, 0xe0, + 0x0f, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x03, 0xf9, 0xfb, 0xff, 0x7f, 0xff, + 0x3f, 0xff, 0x1f, 0xff, 0x0f, 0xe0, 0x0f, 0xff, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xcf, 0xe7, 0xff, 0x80, 0x03, + 0xff, 0xfb, 0xf9, 0xfe, 0x7f, 0xff, 0x3f, 0xf8, 0x1f, 0xfc, 0x0f, 0xff, + 0x8f, 0xdf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xff, 0xc0, 0x07, 0xff, 0x80, 0x03, 0xff, 0xfb, 0xf1, 0xfe, 0xff, 0xff, + 0xbf, 0x00, 0x1f, 0x80, 0x0f, 0xff, 0x8f, 0xcf, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xc0, 0x07, 0xff, 0x80, 0x03, + 0xff, 0xf3, 0xf1, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x1f, 0x80, 0x1f, 0xff, + 0x9f, 0xcf, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, + 0xff, 0x80, 0x03, 0xff, 0x80, 0x03, 0xff, 0xe3, 0xf0, 0xff, 0xfc, 0x3f, + 0xff, 0x00, 0x3f, 0x80, 0x1f, 0xff, 0x9f, 0xcf, 0xc0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0x03, 0x81, 0xff, 0x00, 0x03, + 0xff, 0xc3, 0xf0, 0xff, 0xf8, 0x3f, 0xff, 0x00, 0x3f, 0x80, 0x1f, 0xff, + 0x9f, 0x8f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfe, 0x0f, 0xf0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfc, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x3f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // 'adafruit_wippersnapper_logo', 240x240px const unsigned char tft_bmp_logo_240240[] PROGMEM = { diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 2d2d548f0..15a746ffc 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -17,9 +17,7 @@ /*! @brief Constructs a new DisplayController object */ -DisplayController::DisplayController() { - _last_bar_update = 0; -} +DisplayController::DisplayController() { _last_bar_update = 0; } /*! @brief Destructor @@ -110,12 +108,12 @@ bool DisplayController::Handle_Display_Remove( return false; DisplayHardware *display = findDisplay(msgRemove->name); - + if (display == nullptr) - return false; // Display not found - + return false; // Display not found + // Remove from vector - for (std::vector::iterator it = _hw_instances.begin(); + for (std::vector::iterator it = _hw_instances.begin(); it != _hw_instances.end(); ++it) { if (*it == display) { delete *it; @@ -124,7 +122,7 @@ bool DisplayController::Handle_Display_Remove( return true; } } - + return false; } @@ -169,7 +167,7 @@ void DisplayController::update(int32_t rssi, bool is_connected) { // Only update the status bar every 60 seconds unsigned long now = millis(); if (now - _last_bar_update < 60000) - return; + return; _last_bar_update = now; // Get the driver instance for the display @@ -189,11 +187,12 @@ void DisplayController::update(int32_t rssi, bool is_connected) { * @param name The name of the display to find. * @return Pointer to the DisplayHardware instance if found, nullptr otherwise. */ -DisplayHardware* DisplayController::findDisplay(const char* name) { +DisplayHardware *DisplayController::findDisplay(const char *name) { if (name == nullptr) return nullptr; - - for (std::vector::iterator it = _hw_instances.begin(); it != _hw_instances.end(); ++it) { + + for (std::vector::iterator it = _hw_instances.begin(); + it != _hw_instances.end(); ++it) { if (*it != nullptr && strcmp((*it)->getName(), name) == 0) { return *it; } diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index 17decf538..f68402c28 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -160,7 +160,7 @@ class dispDrvSt7789 : public dispDrvBase { _display->drawBitmap(_statusbar_icon_battery_x, _statusbar_icons_y, epd_bmp_bat_full, ST7789_STATUSBAR_ICON_SZ, ST7789_STATUSBAR_ICON_SZ, ST77XX_BLACK); - + // Reset text color and size for main text area _display->setTextColor(ST77XX_WHITE); _display->setTextSize(_text_sz); diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index a06f5062f..12b691ca7 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -195,11 +195,10 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { } // Clear and draw the new WiFi icon, based on RSSI _display->fillRect(_statusbar_icon_wifi_x, _statusbar_icons_y, - STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, - EPD_WHITE); + STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, EPD_WHITE); _display->drawBitmap(_statusbar_icon_wifi_x, _statusbar_icons_y, - wifi_icon, STATUS_BAR_ICON_SZ, - STATUS_BAR_ICON_SZ, EPD_BLACK); + wifi_icon, STATUS_BAR_ICON_SZ, STATUS_BAR_ICON_SZ, + EPD_BLACK); _statusbar_rssi = rssi; } From db0d04bf6000f002ed00b27d41755f4d6e3ff11d Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 7 Oct 2025 09:11:08 -0400 Subject: [PATCH 71/76] Clang --- src/components/display/controller.h | 3 +- src/components/display/drivers/dispDrvBase.h | 38 ++++++++++---------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/components/display/controller.h b/src/components/display/controller.h index 32d080af7..db463b3d4 100644 --- a/src/components/display/controller.h +++ b/src/components/display/controller.h @@ -36,8 +36,9 @@ class DisplayController { bool Handle_Display_Remove(wippersnapper_display_v1_DisplayRemove *msgRemove); bool Handle_Display_Write(wippersnapper_display_v1_DisplayWrite *msgWrite); void update(int32_t rssi, bool is_connected); + private: - DisplayHardware* findDisplay(const char* name); + DisplayHardware *findDisplay(const char *name); std::vector _hw_instances; ///< Holds pointers to DisplayHardware instances unsigned long _last_bar_update; ///< Timestamp of last status bar update diff --git a/src/components/display/drivers/dispDrvBase.h b/src/components/display/drivers/dispDrvBase.h index 242c2e50a..a9fa11b68 100644 --- a/src/components/display/drivers/dispDrvBase.h +++ b/src/components/display/drivers/dispDrvBase.h @@ -157,31 +157,31 @@ class dispDrvBase { @note This method can be overridden by derived classes to provide specific functionality. */ - virtual void updateStatusBar(int8_t rssi, uint8_t bat, - bool mqtt_status) { + virtual void updateStatusBar(int8_t rssi, uint8_t bat, bool mqtt_status) { // No-op for base class } protected: - int16_t _pin_dc; ///< Data/Command pin - int16_t _pin_rst; ///< Reset pin - int16_t _pin_cs; ///< Chip Select pin - int16_t _pin_busy; ///< Optional Busy pin - int16_t _pin_sram_cs; ///< Optional EPD SRAM chip select pin - uint16_t _pin_mosi; ///< Optional MOSI pin for SPI TFT displays - uint16_t _pin_miso; ///< Optional MISO pin for SPI TFT displays - uint16_t _pin_sck; ///< Optional SCK pin for SPI TFT displays - uint8_t _text_sz = 1; ///< Text size for displaying a message - int16_t _height; ///< Height of the display - int16_t _width; ///< Width of the display - uint8_t _rotation; ///< Rotation of the display + int16_t _pin_dc; ///< Data/Command pin + int16_t _pin_rst; ///< Reset pin + int16_t _pin_cs; ///< Chip Select pin + int16_t _pin_busy; ///< Optional Busy pin + int16_t _pin_sram_cs; ///< Optional EPD SRAM chip select pin + uint16_t _pin_mosi; ///< Optional MOSI pin for SPI TFT displays + uint16_t _pin_miso; ///< Optional MISO pin for SPI TFT displays + uint16_t _pin_sck; ///< Optional SCK pin for SPI TFT displays + uint8_t _text_sz = 1; ///< Text size for displaying a message + int16_t _height; ///< Height of the display + int16_t _width; ///< Width of the display + uint8_t _rotation; ///< Rotation of the display // statusbar properties - int _statusbar_icons_y; ///< Y position of status bar icons + int _statusbar_icons_y; ///< Y position of status bar icons int _statusbar_icon_battery_x; ///< X position of battery icon - int _statusbar_icon_wifi_x; ///< X position of WiFi icon - int _statusbar_icon_cloud_x; ///< X position of cloud icon - int8_t _statusbar_rssi; ///< RSSI value for status bar - uint8_t _statusbar_bat; ///< Battery level, as a percentage, for the status bar + int _statusbar_icon_wifi_x; ///< X position of WiFi icon + int _statusbar_icon_cloud_x; ///< X position of cloud icon + int8_t _statusbar_rssi; ///< RSSI value for status bar + uint8_t + _statusbar_bat; ///< Battery level, as a percentage, for the status bar bool _statusbar_mqtt_connected; ///< MQTT connection status for the status bar }; From f4161e352b5b5c0efddfa7bb578f6537fd288c6d Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 7 Oct 2025 09:24:03 -0400 Subject: [PATCH 72/76] Clang --- src/components/register/Wippersnapper_Register.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/register/Wippersnapper_Register.cpp b/src/components/register/Wippersnapper_Register.cpp index 738f05cca..4ee1f2733 100644 --- a/src/components/register/Wippersnapper_Register.cpp +++ b/src/components/register/Wippersnapper_Register.cpp @@ -77,7 +77,7 @@ bool Wippersnapper::encodePubRegistrationReq() { /****************************************************************************/ void Wippersnapper::pollRegistrationResp() { // Blocking loop, WDT reset upon failure. - //WS._boardStatus = WS_BOARD_DEF_OK; + // WS._boardStatus = WS_BOARD_DEF_OK; while (WS._boardStatus != WS_BOARD_DEF_OK) { WS_DEBUG_PRINT("Polling for registration message response..."); WS_DEBUG_PRINTLN(WS._boardStatus); From b0c6670c64a9e763927b9b882f551e8f7a2feb76 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 7 Oct 2025 12:26:17 -0400 Subject: [PATCH 73/76] clang and doxygen --- src/components/display/assets/icons.h | 54 ++++++++++++++----- src/components/display/assets/splash.h | 25 +++++++-- .../display/drivers/dispDrvSt7789.h | 2 + .../dispDrvThinkInkGrayscale4Eaamfgn.h | 2 + src/components/display/hardware.cpp | 20 ++++++- 5 files changed, 85 insertions(+), 18 deletions(-) diff --git a/src/components/display/assets/icons.h b/src/components/display/assets/icons.h index 13183ff02..feff4ead6 100644 --- a/src/components/display/assets/icons.h +++ b/src/components/display/assets/icons.h @@ -1,45 +1,73 @@ +/*! + * @file src/components/display/assets/icons.h + * + * Icon assets for displays. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ #ifndef _ICONS_H_ #define _ICONS_H_ #include -const unsigned char epd_bmp_cloud_online[] PROGMEM = { - // 'cloud-thin-full, 16x16px +/** + * @brief cloud-thin-full icon from FontAwesome (16x16px) + */ +const unsigned char epd_bmp_cloud_online[] = { 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0d, 0xc0, 0x18, 0x78, 0x10, 0x0c, 0x30, 0x04, 0x70, 0x0c, 0xc0, 0x06, 0xc0, 0x03, 0xc0, 0x03, 0x40, 0x03, 0x70, 0x06, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00}; +/** + * @brief cloud-xmark-thin-full icon from FontAwesome (16x16px) + */ const unsigned char epd_bmp_cloud_offline[] PROGMEM = { - // 'cloud-xmark-thin-full, 16x16px 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x0d, 0xc0, 0x18, 0x78, 0x10, 0x0c, 0x30, 0x04, 0x73, 0xcc, 0xe3, 0x86, 0xc3, 0xc3, 0xc3, 0xc3, 0x40, 0x03, 0x70, 0x06, 0x3f, 0xfc, 0x00, 0x00, 0x00, 0x00}; -const unsigned char epd_bmp_wifi_full[] PROGMEM = { - // 'wifi-thin-full, 16x16px +/** + * @brief wifi-thin-full icon from FontAwesome (16x16px) + */ +const unsigned char epd_bmp_wifi_full[] = { 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x3c, 0x3c, 0x70, 0x0e, 0xc0, 0x03, 0x03, 0xc0, 0x0f, 0xf0, 0x1c, 0x38, 0x18, 0x18, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00}; -const unsigned char epd_bmp_wifi_fair[] PROGMEM = { - // 'wifi-fair-thin-full, 16x16px +/** + * @brief wifi-fair-thin-full icon from FontAwesome (16x16px) + */ +const unsigned char epd_bmp_wifi_fair[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x0f, 0xf0, 0x1c, 0x38, 0x18, 0x18, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00}; -const unsigned char epd_bmp_wifi_weak[] PROGMEM = { - // 'wifi-weak-thin-full, 16x16px +/** + * @brief wifi-weak-thin-full icon from FontAwesome (16x16px) + */ +const unsigned char epd_bmp_wifi_weak[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00}; -const unsigned char epd_bmp_wifi_no_signal[] PROGMEM = { - // 'wifi-slash-thin-full, 16x16px +/** + * @brief wifi-slash-thin-full icon from FontAwesome (16x16px) + */ +const unsigned char epd_bmp_wifi_no_signal[] = { 0x00, 0x00, 0x40, 0x00, 0x27, 0xc0, 0x1e, 0x38, 0x68, 0x00, 0x44, 0x03, 0x03, 0x00, 0x01, 0xe0, 0x08, 0x90, 0x00, 0x40, 0x00, 0x20, 0x01, 0x90, 0x03, 0x88, 0x01, 0x84, 0x00, 0x02, 0x00, 0x00}; -const unsigned char epd_bmp_bat_full[] PROGMEM = { - // 'battery-full-thin-full, 16x16px +/** + * @brief battery-full-thin-full icon from FontAwesome (16x16px) + */ +const unsigned char epd_bmp_bat_full[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0xc0, 0x06, 0xff, 0xfa, 0xf0, 0x0b, 0xf0, 0x0b, 0xf0, 0x0b, 0xf0, 0x0b, 0xff, 0xfa, 0xc0, 0x06, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/src/components/display/assets/splash.h b/src/components/display/assets/splash.h index 254a60b65..361b8e0e6 100644 --- a/src/components/display/assets/splash.h +++ b/src/components/display/assets/splash.h @@ -1,9 +1,25 @@ +/*! + * @file src/components/display/assets/splash.h + * + * Splash screen assets for displays. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Copyright (c) Brent Rubell 2025 for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * + */ #ifndef _SPLASH_H_ #define _SPLASH_H_ #include -const unsigned char tft_bmp_logo_240135[] PROGMEM = { - // 'adafruit_wippersnapper_logo, 240x135px +/** + * @brief Wippersnapper logo, 296x128px + */ +const unsigned char tft_bmp_logo_240135[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -343,9 +359,10 @@ const unsigned char tft_bmp_logo_240135[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -// 'adafruit_wippersnapper_logo', 240x240px +/** + * @brief Wippersnapper logo, 240x240px + */ const unsigned char tft_bmp_logo_240240[] PROGMEM = { - // 'adafruit_wippersnapper_logo, 240x240px 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index f68402c28..a415c576c 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -120,6 +120,8 @@ class dispDrvSt7789 : public dispDrvBase { /*! @brief Draws a status bar at the top of the display. + @param io_username + The Adafruit IO username to display on the status bar. */ virtual void drawStatusBar(const char *io_username) override { if (!_display) diff --git a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h index 12b691ca7..291174f64 100644 --- a/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -96,6 +96,8 @@ class drvDispThinkInkGrayscale4Eaamfgn : public dispDrvBase { /*! @brief Draws a status bar at the top of the display. + @param io_username + The Adafruit IO username to display on the status bar. */ virtual void drawStatusBar(const char *io_username) override { if (!_display) diff --git a/src/components/display/hardware.cpp b/src/components/display/hardware.cpp index 7228fe36f..ff0ffec84 100644 --- a/src/components/display/hardware.cpp +++ b/src/components/display/hardware.cpp @@ -152,7 +152,7 @@ wippersnapper_display_v1_DisplayType DisplayHardware::getType() { } /*! - @brief Parses a pin string (e.g., "D5") and returns the corresponding pin +@brief Parses a pin string (e.g., "D5") and returns the corresponding pin number. @param pinStr The pin string to parse. @@ -250,18 +250,36 @@ bool DisplayHardware::beginEPD( return true; } +/*! + @brief Displays the splash screen on the display. +*/ void DisplayHardware::showSplash() { if (!_drvDisp) return; _drvDisp->showSplash(); } +/*! + @brief Draws a status bar at the top of the display. + @param io_username + The Adafruit IO username to display on the status bar. +*/ void DisplayHardware::drawStatusBar(const char *io_username) { if (!_drvDisp) return; _drvDisp->drawStatusBar(io_username); } +/*! + @brief Updates the status bar with the latest RSSI, battery, and MQTT + connection status. + @param rssi + The current WiFi RSSI value. + @param bat + The current battery percentage (0-100). + @param mqtt_connected + True if connected to MQTT, False otherwise. +*/ void DisplayHardware::updateStatusBar(int8_t rssi, uint8_t bat, bool mqtt_connected) { if (!_drvDisp) From 7219d513f83661540fb334c45fc7b3d230168660 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 7 Oct 2025 13:21:05 -0400 Subject: [PATCH 74/76] Remove empty ws_sdcard files --- src/provisioning/sdcard/ws_sdcard.cpp | 0 src/provisioning/sdcard/ws_sdcard.h | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/provisioning/sdcard/ws_sdcard.cpp delete mode 100644 src/provisioning/sdcard/ws_sdcard.h diff --git a/src/provisioning/sdcard/ws_sdcard.cpp b/src/provisioning/sdcard/ws_sdcard.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/provisioning/sdcard/ws_sdcard.h b/src/provisioning/sdcard/ws_sdcard.h deleted file mode 100644 index e69de29bb..000000000 From 4fe998ada7ab321ab2c73bf951eceff406fc6a06 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 7 Oct 2025 13:23:37 -0400 Subject: [PATCH 75/76] Address @tyeth review --- library.properties | 2 +- platformio.ini | 7 +++---- src/Wippersnapper.cpp | 5 ----- src/components/display/controller.cpp | 6 +++--- src/components/register/Wippersnapper_Register.cpp | 3 +-- 5 files changed, 8 insertions(+), 15 deletions(-) diff --git a/library.properties b/library.properties index 905925a78..f2fd936c0 100644 --- a/library.properties +++ b/library.properties @@ -7,4 +7,4 @@ paragraph=Arduino application for Adafruit.io WipperSnapper category=Communication url=https://github.com/adafruit/Adafruit_Wippersnapper_Arduino architectures=* -depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library, Adafruit AS5600 Library, Adafruit BMP5xx Library, Adafruit MLX90632 Library, Adafruit EPD, Adafruit SPA06_003, Adafruit QMC5883P Library +depends=OmronD6T - Community Fork, SdFat - Adafruit Fork, Adafruit NeoPixel, Adafruit SPA06_003, Adafruit SPIFlash, ArduinoJson, Adafruit DotStar, Adafruit HDC302x, Adafruit INA219, Adafruit INA260 Library, Adafruit INA237 and INA238 Library, Adafruit LTR329 and LTR303, Adafruit LTR390 Library, Adafruit MCP3421, Adafruit MLX90632 Library, Adafruit NAU7802 Library, Adafruit SleepyDog Library, Adafruit TMP117, Adafruit TinyUSB Library, Adafruit AHTX0, Adafruit AS5600 Library, Adafruit BME280 Library, Adafruit BMP280 Library, Adafruit BMP3XX Library, Adafruit BMP5xx Library, Adafruit DPS310, Adafruit DS248x, Adafruit SCD30, Adafruit SGP30 Sensor, Adafruit SGP40 Sensor, Sensirion I2C SCD4x, Sensirion I2C SEN5X, Sensirion I2C SEN66, arduino-sht, Adafruit Si7021 Library, Adafruit MQTT Library, Adafruit MS8607, Adafruit MCP9808 Library, Adafruit MCP9600 Library, Adafruit MPL115A2, Adafruit MPRLS Library, Adafruit TSL2591 Library, Adafruit_VL53L0X, Adafruit VL53L1X, STM32duino VL53L4CD, STM32duino VL53L4CX, Adafruit_VL6180X, Adafruit PM25 AQI Sensor, Adafruit QMC5883P Library, Adafruit VCNL4020 Library, Adafruit VCNL4040, Adafruit VCNL4200 Library, Adafruit VEML7700 Library, Adafruit LC709203F, Adafruit LPS2X, Adafruit LPS28, Adafruit LPS35HW, Adafruit seesaw Library, Adafruit BME680 Library, Adafruit MAX1704X, Adafruit ADT7410 Library, Adafruit HTS221, Adafruit HTU21DF Library, Adafruit HTU31D Library, Adafruit PCT2075, hp_BH1750, ENS160 - Adafruit Fork, Adafruit BusIO, Adafruit Unified Sensor, Sensirion Core, Adafruit GFX Library, Adafruit LED Backpack Library, Adafruit LiquidCrystal, Adafruit SH110X, Adafruit SSD1306, Adafruit EPD, Adafruit ST7735 and ST7789 Library diff --git a/platformio.ini b/platformio.ini index 7f92de3ff..4be3bb597 100644 --- a/platformio.ini +++ b/platformio.ini @@ -83,6 +83,8 @@ lib_deps = adafruit/Adafruit PM25 AQI Sensor adafruit/Adafruit SH110X adafruit/Adafruit SSD1306 + adafruit/Adafruit EPD + adafruit/Adafruit ST7735 and ST7789 Library https://github.com/tyeth/omron-devhub_d6t-arduino.git https://github.com/pstolarz/OneWireNg.git ; COMMENT OUT FOR RP2040/RP2350 BOARDS @@ -96,9 +98,6 @@ lib_deps = https://github.com/adafruit/WiFiNINA.git https://github.com/Starmbi/hp_BH1750.git https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git - Adafruit EPD - Adafruit ST7735 and ST7789 Library - ; Common build environment for ESP32 platform [common:esp32] @@ -263,7 +262,7 @@ extra_scripts = pre:rename_usb_config.py extends = common:esp32 board = adafruit_magtag29_esp32s2 build_flags = -DARDUINO_MAGTAG29_ESP32S2 -DBOARD_HAS_PSRAM -;set partition to tinyuf2-partitions-4MB.csv as of idf 5.1 +;set partition to tinyuf2-partitions-4MB-noota.csv as of CPY 10 board_build.partitions = tinyuf2-partitions-4MB-noota.csv extra_scripts = pre:rename_usb_config.py diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index 44d6afb1e..5a189241c 100644 --- a/src/Wippersnapper.cpp +++ b/src/Wippersnapper.cpp @@ -2820,11 +2820,6 @@ void Wippersnapper::connect() { runNetFSM(); WS.feedWDT(); - // Initialize Digital IO class - WS._digitalGPIO = new Wippersnapper_DigitalGPIO(20); - // Initialize Analog IO class - WS._analogIO = new Wippersnapper_AnalogIO(5, 3.3); - // Configure hardware while (!WS.pinCfgCompleted) { WS_DEBUG_PRINTLN( diff --git a/src/components/display/controller.cpp b/src/components/display/controller.cpp index 15a746ffc..31595b0c3 100644 --- a/src/components/display/controller.cpp +++ b/src/components/display/controller.cpp @@ -83,9 +83,9 @@ bool DisplayController::Handle_Display_AddOrReplace( return false; } - WS.feedWDT(); + WS.runNetFSM(); display->showSplash(); - WS.feedWDT(); + WS.runNetFSM(); display->drawStatusBar(WS._config.aio_user); WS.feedWDT(); @@ -146,8 +146,8 @@ bool DisplayController::Handle_Display_Write( // Write the message to the display WS_DEBUG_PRINT("[display] Writing message to display: "); WS_DEBUG_PRINTLN(msgWrite->message); + WS.runNetFSM(); display->writeMessage(msgWrite->message); - WS.feedWDT(); WS.runNetFSM(); return true; } diff --git a/src/components/register/Wippersnapper_Register.cpp b/src/components/register/Wippersnapper_Register.cpp index 4ee1f2733..c38a4dbd2 100644 --- a/src/components/register/Wippersnapper_Register.cpp +++ b/src/components/register/Wippersnapper_Register.cpp @@ -8,7 +8,7 @@ * please support Adafruit and open-source hardware by purchasing * products from Adafruit! * - * Copyright (c) Brent Rubell 2021 for Adafruit Industries. + * Copyright (c) Brent Rubell 2021-2025 for Adafruit Industries. * * BSD license, all text here must be included in any redistribution. * @@ -77,7 +77,6 @@ bool Wippersnapper::encodePubRegistrationReq() { /****************************************************************************/ void Wippersnapper::pollRegistrationResp() { // Blocking loop, WDT reset upon failure. - // WS._boardStatus = WS_BOARD_DEF_OK; while (WS._boardStatus != WS_BOARD_DEF_OK) { WS_DEBUG_PRINT("Polling for registration message response..."); WS_DEBUG_PRINTLN(WS._boardStatus); From 1178bb8d7ae7608d513eac0a1061d11fa05a8770 Mon Sep 17 00:00:00 2001 From: brentru Date: Tue, 7 Oct 2025 16:28:27 -0400 Subject: [PATCH 76/76] Fix: Artifacts when writing second line > chars than first --- src/components/display/drivers/dispDrvSt7789.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/display/drivers/dispDrvSt7789.h b/src/components/display/drivers/dispDrvSt7789.h index a415c576c..3bbd3d4f4 100644 --- a/src/components/display/drivers/dispDrvSt7789.h +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -245,8 +245,9 @@ class dispDrvSt7789 : public dispDrvBase { return; // Clear only the area below the status bar - _display->fillRect(0, ST7789_STATUSBAR_HEIGHT, _width, - _height - ST7789_STATUSBAR_HEIGHT, ST77XX_BLACK); + _display->fillRect(0, ST7789_STATUSBAR_HEIGHT, _display->width(), + _display->height() - ST7789_STATUSBAR_HEIGHT, + ST77XX_BLACK); int16_t y_idx = ST7789_STATUSBAR_HEIGHT; // Calculate the line height based on the text size (NOTE: base height is