diff --git a/.github/workflows/build-clang-doxy.yml b/.github/workflows/build-clang-doxy.yml index 984cb71b4..c13ec6432 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 @@ -92,8 +92,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 @@ -123,12 +121,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 @@ -311,8 +303,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 @@ -342,12 +332,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 @@ -865,8 +849,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 @@ -896,12 +878,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 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/.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/Doxyfile b/Doxyfile index c05228416..2e9f261f9 100644 --- a/Doxyfile +++ b/Doxyfile @@ -2451,4 +2451,4 @@ GENERATE_LEGEND = YES # plantuml temporary files. # The default value is: YES. -DOT_CLEANUP = YES +DOT_CLEANUP = YES \ No newline at end of file diff --git a/library.properties b/library.properties index 020d6d698..f2fd936c0 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 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 72ef18f8e..4be3bb597 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 @@ -92,12 +83,14 @@ 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 - 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 @@ -106,8 +99,6 @@ lib_deps = https://github.com/Starmbi/hp_BH1750.git https://github.com/adafruit/Adafruit_TinyUSB_Arduino.git - - ; Common build environment for ESP32 platform [common:esp32] platform = https://github.com/pioarduino/platform-espressif32/releases/download/53.03.13/platform-espressif32.zip @@ -217,7 +208,6 @@ 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 -;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 @@ -307,35 +297,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-noota.csv as of CPY 10 -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 diff --git a/src/Wippersnapper.cpp b/src/Wippersnapper.cpp index ca3cca100..5a189241c 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(); }; /**************************************************************************/ @@ -105,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(); @@ -140,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 } /**************************************************************************/ @@ -291,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; @@ -462,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; @@ -559,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!"); } @@ -963,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 @@ -976,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: "); @@ -989,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 @@ -1043,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 == @@ -1071,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!"); @@ -1142,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 } @@ -1156,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; } @@ -1191,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"); @@ -1209,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 detach 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"); @@ -1237,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: "); @@ -1251,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"); @@ -1271,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; @@ -1447,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; } @@ -1655,6 +1528,124 @@ 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) { + 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); + + // 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_PRINTLN("Publishing DisplayResponse Message..."); + if (!WS._mqtt->publish(WS._topic_signal_display_device, WS._buffer_outgoing, + msgSz, 0)) { + WS_DEBUG_PRINTLN("ERROR: Failed to Publish DisplayResponse!"); + } else { + WS_DEBUG_PRINTLN("Published!"); + } + } 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; + } + // 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; +} + +/*! + @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 + WS.msgSignalDisplay.cb_payload.funcs.decode = cbDecodeDisplayMsg; + + // Decode pixel message from buffer + pb_istream_t istream = pb_istream_from_buffer(WS._buffer, WS.bufSize); + if (!ws_pb_decode(&istream, wippersnapper_signal_v1_DisplayRequest_fields, + &WS.msgSignalDisplay)) + WS_DEBUG_PRINTLN("ERROR: Unable to decode display message"); +} + /****************************************************************************/ /*! @brief Handles MQTT messages on signal topic until timeout. @@ -1723,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"); } @@ -1758,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) { @@ -1783,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 } /**************************************************************************/ @@ -2344,6 +2317,63 @@ bool Wippersnapper::generateWSTopics() { WS_DEBUG_PRINTLN("FATAL ERROR: Failed to allocate memory for UART topic!"); return false; } + + // /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(topicLen); +#else + WS._topic_signal_display_brkr = (char *)malloc(topicLen); +#endif + + // Generate the topic + if (WS._topic_signal_display_brkr != NULL) { + 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 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 + 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(topicLen); +#else + WS._topic_signal_display_device = (char *)malloc(topicLen); +#endif + + // Generate the topic if memory was allocated successfully + if (WS._topic_signal_display_device != NULL) { + 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; + } + return true; } @@ -2398,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; } @@ -2410,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); } @@ -2448,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); } @@ -2461,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; @@ -2494,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); @@ -2616,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(); } @@ -2816,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()) { @@ -2829,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 - // Configure hardware while (!WS.pinCfgCompleted) { WS_DEBUG_PRINTLN( @@ -2884,8 +2867,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!"); + } } /**************************************************************************/ @@ -2925,5 +2912,9 @@ ws_status_t Wippersnapper::run() { WS._uartComponent->update(); WS.feedWDT(); + // Process display controller events, if initialized + WS._displayController->update(getRSSI(), WS._mqtt->connected()); + WS.feedWDT(); + return WS_NET_CONNECTED; // TODO: Make this funcn void! } diff --git a/src/Wippersnapper.h b/src/Wippersnapper.h index 205514927..6395bcb98 100644 --- a/src/Wippersnapper.h +++ b/src/Wippersnapper.h @@ -123,12 +123,7 @@ #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" #include "components/pwm/ws_pwm.h" @@ -144,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 @@ -155,6 +150,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 \ @@ -234,10 +230,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 @@ -247,6 +239,7 @@ class ws_pwm; class ws_ds18x20; class ws_pixels; class ws_uart; +class DisplayController; /**************************************************************************/ /*! @@ -360,16 +353,13 @@ 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 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 */ @@ -407,6 +397,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. */ wippersnapper_signal_v1_CreateSignalRequest _incomingSignalMsg; /*!< Incoming signal message from broker */ @@ -433,6 +427,9 @@ class Wippersnapper { wippersnapper_signal_v1_UARTRequest msgSignalUART; ///< UARTReq wrapper message + 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 milliseconds. */ @@ -493,6 +490,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_Boards.h b/src/Wippersnapper_Boards.h index 9bf4010fb..0c9363b7f 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/assets/icons.h b/src/components/display/assets/icons.h new file mode 100644 index 000000000..feff4ead6 --- /dev/null +++ b/src/components/display/assets/icons.h @@ -0,0 +1,75 @@ +/*! + * @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 + +/** + * @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 = { + 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}; + +/** + * @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}; + +/** + * @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}; + +/** + * @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}; + +/** + * @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}; + +/** + * @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}; + +#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 new file mode 100644 index 000000000..361b8e0e6 --- /dev/null +++ b/src/components/display/assets/splash.h @@ -0,0 +1,1366 @@ +/*! + * @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 + +/** + * @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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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}; + +/** + * @brief Wippersnapper logo, 240x240px + */ +const unsigned char tft_bmp_logo_240240[] PROGMEM = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 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[] = { + // '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/controller.cpp b/src/components/display/controller.cpp new file mode 100644 index 000000000..31595b0c3 --- /dev/null +++ b/src/components/display/controller.cpp @@ -0,0 +1,202 @@ +/*! + * @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() { _last_bar_update = 0; } + +/*! + @brief Destructor +*/ +DisplayController::~DisplayController() { + // Clean up all display hardware instances + for (DisplayHardware *hw_instance : _hw_instances) { + delete hw_instance; + } + _hw_instances.clear(); +} + +/*! + @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(msgAdd->name); + WS_DEBUG_PRINT("[display] Adding or replacing display: "); + WS_DEBUG_PRINTLN(msgAdd->name); + + // Does this display hw instance already exist? + 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 + display->setType(msgAdd->type); + + // Attempt to initialize display hardware instance + bool did_begin = false; + if (msgAdd->which_config == + 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!"); + delete display; + 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; + } + + WS.runNetFSM(); + display->showSplash(); + WS.runNetFSM(); + display->drawStatusBar(WS._config.aio_user); + WS.feedWDT(); + + _hw_instances.push_back(display); // Store the display instance + WS_DEBUG_PRINTLN("[display] Display added or replaced successfully!"); + WS.feedWDT(); + WS.runNetFSM(); + return true; +} + +/*! + @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) { + 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; + } + } + + 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 = findDisplay(msgWrite->name); + + // Early-out if driver instance not found + if (!display) { + WS_DEBUG_PRINTLN("[display] Failed to write, driver not found!"); + return false; + } + + // 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.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; + + // 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 + // yet. + WS_DEBUG_PRINTLN("[display] Updating status bar..."); + hw_instance->updateStatusBar(rssi, 100, 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 new file mode 100644 index 000000000..db463b3d4 --- /dev/null +++ b/src/components/display/controller.h @@ -0,0 +1,47 @@ +/*! + * @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_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 +}; +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 new file mode 100644 index 000000000..a9fa11b68 --- /dev/null +++ b/src/components/display/drivers/dispDrvBase.h @@ -0,0 +1,188 @@ +/*! + * @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 "../assets/icons.h" +#include "../assets/splash.h" +#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) {} + + /*! + @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 + 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) { return false; } + + /*! + @brief Attempts to initialize a SPI TFT driver. + @return True if the display was initialized successfully, false otherwise. + */ + virtual bool begin() { return false; } + + /*! + @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; + + /*! + @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; } + + /*! + @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 + } + + /*! + @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 + } + + /*! + @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, 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 + // 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 new file mode 100644 index 000000000..3bbd3d4f4 --- /dev/null +++ b/src/components/display/drivers/dispDrvSt7789.h @@ -0,0 +1,296 @@ +/*! + * @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 + +#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. +*/ +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) {} + + /*! + @brief Destructor for the ST7789 display driver. + */ + ~dispDrvSt7789() { + if (_display) { + 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 + } + + /*! + @brief Attempts to initialize the ST7789 TFT driver. + @return True if the display was initialized successfully, false otherwise. + */ + bool begin() override { + + _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); + + // Turn on backlight +#if defined(ARDUINO_FUNHOUSE_ESP32S2) + 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; + } + + /*! + @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_WHITE); + } else if (_width == 135 && _height == 240) { + _display->drawBitmap(0, 0, tft_bmp_logo_240135, 240, 135, ST77XX_WHITE); + } else { + // Unsupported resolution detected, skip splash screen + return; + } + + delay(500); + } + + /*! + @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) + return; + + // Clear the entire display buffer to remove splash screen + _display->fillScreen(ST77XX_BLACK); + + // Draw status bar + _display->fillRect(0, 0, _display->width(), ST7789_STATUSBAR_HEIGHT, + ST77XX_WHITE); + + // Draw username on left side of the status bar + _display->setTextSize(1); + _display->setTextColor(ST77XX_BLACK); + _display->setCursor(5, 6); + _display->print(io_username); + + // 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); + + // Reset text color and size for main text area + _display->setTextColor(ST77XX_WHITE); + _display->setTextSize(_text_sz); + } + + /*! + @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; + + // 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; + + // 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(_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); + } else { + _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) + 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; + } + } + + /*! + @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 ST7789 driver. + */ + virtual void writeMessage(const char *message) override { + if (_display == nullptr) + return; + + // Clear only the area below the status bar + _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 + // 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; + 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/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h new file mode 100644 index 000000000..291174f64 --- /dev/null +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4Eaamfgn.h @@ -0,0 +1,274 @@ +/*! + * @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) + * + * 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" + +#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 +#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. +*/ +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) {} + + ~drvDispThinkInkGrayscale4Eaamfgn() { + 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_EAAMFGN(_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 + _display->setTextSize(_text_sz); + _display->setTextColor(EPD_BLACK); + _display->setTextWrap(false); + _height = _display->height(); + _width = _display->width(); + _display->clearBuffer(); + return true; + } + + /*! + @brief Displays a splash screen + */ + virtual void showSplash() override { + if (!_display) + return; + _display->drawBitmap(0, 0, epd_bitmap_ws_logo_296128, 296, 128, EPD_BLACK); + _display->display(); + } + + /*! + @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) + return; + + // Clear the entire display buffer to remove splash screen + _display->clearBuffer(); + + // Draw status bar + _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); + _display->setTextColor(EPD_BLACK); + _display->setCursor(5, 6); + _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; + // 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, + 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(); + } + + /*! + @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; + + // 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; + + // No need to update if nothing has changed + if (!update_rssi && !update_mqtt) + return; + + 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 { + 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(); + } + + /*! + @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; + + // Clear only the area below the status bar + _display->fillRect(0, STATUS_BAR_HEIGHT, _display->width(), + _display->height() - STATUS_BAR_HEIGHT, EPD_WHITE); + // 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 + // 8px) + 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; + 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) { + // Degree symbol + _display->write(char(248)); + i++; + } else { + _display->print(message[i]); + } + } + _display->display(); + } + +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/drivers/dispDrvThinkInkGrayscale4T5.h b/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h new file mode 100644 index 000000000..ed266e00b --- /dev/null +++ b/src/components/display/drivers/dispDrvThinkInkGrayscale4T5.h @@ -0,0 +1,140 @@ +/*! + * @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) + * + * 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 new file mode 100644 index 000000000..ff0ffec84 --- /dev/null +++ b/src/components/display/hardware.cpp @@ -0,0 +1,438 @@ +/*! + * @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 Lambda function to create a dispDrvBase EPD instance. +*/ +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 FactoryDrvDispEpd = { + {"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); + }}, + {"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); + }}}; + +/*! + @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 = { + {"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); + }}, + {"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); + }}}; + +/*! + @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 + 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 *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. + @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, + 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 + The name of the hardware instance. +*/ +DisplayHardware::DisplayHardware(const char *name) { + strncpy(_name, name, sizeof(_name) - 1); + _name[sizeof(_name) - 1] = '\0'; + _type = wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_UNSPECIFIED; +} + +/*! + @brief Destructor +*/ +DisplayHardware::~DisplayHardware() { + if (_drvDisp) { + delete _drvDisp; + _drvDisp = nullptr; + } +} + +/*! + @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 Gets the hardware's display type. + @return The current display type. +*/ +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 + 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) { + // Validate pointers + if (config == nullptr || spi_config == nullptr) { + WS_DEBUG_PRINTLN("[display] EPD config or SPI config is null!"); + return false; + } + + // 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; + } + + // 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 srcs = -1, busy = -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) { + srcs = parsePin(spi_config->pin_sram_cs); + } + if (strlen(spi_config->pin_busy) >= 2) { + busy = parsePin(spi_config->pin_busy); + } + + // Configure SPI bus + if (spi_config->bus != 0) { + WS_DEBUG_PRINTLN( + "[display] ERROR: Non-default SPI buses are currently not supported!"); + return false; + } + + // Create display driver object using the factory function + _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 + } + + // Configure EPD mode + thinkinkmode_t epd_mode = THINKINK_MONO; + 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 { + WS_DEBUG_PRINTLN("[display] ERROR: Unsupported EPD mode!"); + delete _drvDisp; + _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!"); + delete _drvDisp; + _drvDisp = nullptr; + return false; + } + + WS_DEBUG_PRINTLN("[display] Successfully initialized epd display!"); + 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) + return; + _drvDisp->updateStatusBar(rssi, bat, mqtt_connected); +} + +/*! + @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 + 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 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; + } + + int16_t rst = -1, miso = -1; + 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 + 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); + } + + // 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->setTextSize(config->text_size); + _drvDisp->begin(); + + return true; +} + +/*! + @brief Gets the name of the display hardware instance. + @return The name of the display hardware instance. +*/ +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 (!_drvDisp) + return; + _drvDisp->writeMessage(message); +} + +/*! + @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 new file mode 100644 index 000000000..66403a710 --- /dev/null +++ b/src/components/display/hardware.h @@ -0,0 +1,65 @@ +/*! + * @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 "drivers/dispDrvBase.h" +#include "drivers/dispDrvSt7789.h" +#include "drivers/dispDrvThinkInkGrayscale4Eaamfgn.h" +#include "drivers/dispDrvThinkInkGrayscale4T5.h" +#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); + ~DisplayHardware(); + + // + // 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 beginTft(wippersnapper_display_v1_TftConfig *config, + wippersnapper_display_v1_TftSpiConfig *spi_config); + + void showSplash(); + void drawStatusBar(const char *io_username); + 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 + // exposed within dispDrv driver instances + // + void writeMessage(const char *message); + +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 + dispDrvBase *_drvDisp = nullptr; ///< Base display driver +}; +#endif // WS_DISPLAY_HARDWARE_H \ No newline at end of file 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 2ba4b0553..f20391d06 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(); } /*************************************************************/ @@ -1089,6 +1091,7 @@ void WipperSnapper_Component_I2C::updateI2CDeviceProperties( // set response OK _busStatusResponse = wippersnapper_i2c_v1_BusResponse_BUS_RESPONSE_SUCCESS; + WS.runNetFSM(); } /*******************************************************************************/ @@ -1305,9 +1308,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/components/register/Wippersnapper_Register.cpp b/src/components/register/Wippersnapper_Register.cpp index ee27c5e82..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. * 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/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. * 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 2b312bda8..2db5d1bde 100644 --- a/src/provisioning/tinyusb/Wippersnapper_FS.cpp +++ b/src/provisioning/tinyusb/Wippersnapper_FS.cpp @@ -357,15 +357,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(); @@ -446,13 +438,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!"); @@ -463,13 +449,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!"); @@ -523,83 +503,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. */ diff --git a/src/wippersnapper/description/v1/description.pb.c b/src/wippersnapper/description/v1/description.pb.c index af570fc40..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 Fri Jun 6 19:48:16 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 208fbd01c..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 Fri Jun 6 19:48:16 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 new file mode 100644 index 000000000..56076ede4 --- /dev/null +++ b/src/wippersnapper/display/v1/display.pb.c @@ -0,0 +1,39 @@ +/* Automatically generated nanopb constant definitions */ +/* 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 +#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_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) + + +PB_BIND(wippersnapper_display_v1_DisplayRemove, wippersnapper_display_v1_DisplayRemove, AUTO) + + +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_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..33b91cb7d --- /dev/null +++ b/src/wippersnapper/display/v1/display.pb.h @@ -0,0 +1,290 @@ +/* Automatically generated nanopb header */ +/* 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 +#include +#include "nanopb/nanopb.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_EPD = 1, + wippersnapper_display_v1_DisplayType_DISPLAY_TYPE_TFT = 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_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]; + bool did_add; +} wippersnapper_display_v1_DisplayAddedOrReplaced; + +typedef struct _wippersnapper_display_v1_DisplayRemove { + char name[64]; +} 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_DisplayWrite { + char name[64]; + char message[1024]; +} wippersnapper_display_v1_DisplayWrite; + +typedef struct _wippersnapper_display_v1_EPDConfig { + wippersnapper_display_v1_EPDMode mode; + int32_t width; + int32_t height; + int32_t text_size; +} wippersnapper_display_v1_EPDConfig; + +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_TftConfig { + int32_t width; + int32_t height; + int32_t rotation; + int32_t text_size; +} 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; + wippersnapper_display_v1_DisplayDriver driver; + 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 config_epd; + wippersnapper_display_v1_TftConfig config_tft; + } config; +} wippersnapper_display_v1_DisplayAddOrReplace; + + +/* 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_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 +#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" { +#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, 0} +#define wippersnapper_display_v1_TftSpiConfig_init_default {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_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, 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 {"", ""} +#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_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_DisplayWrite_name_tag 1 +#define wippersnapper_display_v1_DisplayWrite_message_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_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 +#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_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 +#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_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) \ +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, INT32, text_size, 4) +#define wippersnapper_display_v1_EPDConfig_CALLBACK NULL +#define wippersnapper_display_v1_EPDConfig_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) \ +X(a, STATIC, SINGULAR, INT32, text_size, 4) +#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, 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 +#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) +#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) +#define wippersnapper_display_v1_DisplayWrite_CALLBACK NULL +#define wippersnapper_display_v1_DisplayWrite_DEFAULT NULL + +#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_DisplayRemoved_FIELDLIST(X, a) \ +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 + +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_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; +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_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 +#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 35 +#define wippersnapper_display_v1_TftSpiConfig_size 53 +#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 +#define wippersnapper_display_v1_DisplayRemoved_size 67 + +#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..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 Fri Jun 6 19:48:16 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 715616f73..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 Fri Jun 6 19:48:16 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 e1e4dde04..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 Fri Jun 6 19:48:16 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 8b5b0f53b..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 Fri Jun 6 19:48:16 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 8ed37f9d0..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 Fri Jun 6 19:48:16 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 14b1a99fe..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 Fri Jun 6 19:48:16 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 e5bcca7f3..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 Fri Jun 6 19:48:16 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 b8a7f6813..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 Fri Jun 6 19:48:16 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 36cf1c440..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 Fri Jun 6 19:48:16 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 d223d7a1c..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 Fri Jun 6 19:48:16 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 eb9b45e93..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 Fri Jun 6 19:48:16 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 61b3b809a..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 Fri Jun 6 19:48:16 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 0f0278ac0..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 Fri Jun 6 19:48:16 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 @@ -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, 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 e459607f3..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 Fri Jun 6 19:48:16 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 @@ -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 1094 +#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 a605be6ef..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 Fri Jun 6 19:48:16 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 af9364c2a..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 Fri Jun 6 19:48:16 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